mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
Merge tag 'fs_for_v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull udf, isofs, ext2, and quota updates from Jan Kara: - Assorted udf & isofs fixes for maliciously formatted devices - Cleanups to use kmalloc() instead of __get_free_page() - Removal of deprecated DAX code from ext2 * tag 'fs_for_v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: validate VAT inode size for old VAT format udf: validate VAT header length against the VAT inode size udf: validate sparing table length as an entry count, not a byte count isofs: bound Rock Ridge symlink components to the SL record ext2: fix ignored return value of generic_write_sync() ext2: Remove deprecated DAX support isofs: replace __get_free_page() with kmalloc() quota: allocate dquot_hash with kmalloc() udf: validate free block extents against the partition length
This commit is contained in:
@@ -114,8 +114,6 @@ struct ext2_sb_info {
|
||||
*/
|
||||
spinlock_t s_lock;
|
||||
struct mb_cache *s_ea_block_cache;
|
||||
struct dax_device *s_daxdev;
|
||||
u64 s_dax_part_off;
|
||||
};
|
||||
|
||||
static inline spinlock_t *
|
||||
@@ -373,11 +371,9 @@ struct ext2_inode {
|
||||
#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
|
||||
#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
|
||||
#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
|
||||
#define EXT2_MOUNT_XIP 0x010000 /* Obsolete, use DAX */
|
||||
#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */
|
||||
#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */
|
||||
#define EXT2_MOUNT_RESERVATION 0x080000 /* Preallocation */
|
||||
#define EXT2_MOUNT_DAX 0x100000 /* Direct Access */
|
||||
|
||||
|
||||
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
|
||||
|
||||
125
fs/ext2/file.c
125
fs/ext2/file.c
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dax.h>
|
||||
#include <linux/filelock.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/iomap.h>
|
||||
@@ -32,111 +31,6 @@
|
||||
#include "acl.h"
|
||||
#include "trace.h"
|
||||
|
||||
#ifdef CONFIG_FS_DAX
|
||||
static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
||||
ssize_t ret;
|
||||
|
||||
if (!iov_iter_count(to))
|
||||
return 0; /* skip atime */
|
||||
|
||||
inode_lock_shared(inode);
|
||||
ret = dax_iomap_rw(iocb, to, &ext2_iomap_ops);
|
||||
inode_unlock_shared(inode);
|
||||
|
||||
file_accessed(iocb->ki_filp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
ssize_t ret;
|
||||
|
||||
inode_lock(inode);
|
||||
ret = generic_write_checks(iocb, from);
|
||||
if (ret <= 0)
|
||||
goto out_unlock;
|
||||
ret = file_remove_privs(file);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
ret = file_update_time(file);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ret = dax_iomap_rw(iocb, from, &ext2_iomap_ops);
|
||||
if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
|
||||
i_size_write(inode, iocb->ki_pos);
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
inode_unlock(inode);
|
||||
if (ret > 0)
|
||||
ret = generic_write_sync(iocb, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lock ordering for ext2 DAX fault paths is:
|
||||
*
|
||||
* mmap_lock (MM)
|
||||
* sb_start_pagefault (vfs, freeze)
|
||||
* address_space->invalidate_lock
|
||||
* address_space->i_mmap_rwsem or page_lock (mutually exclusive in DAX)
|
||||
* ext2_inode_info->truncate_mutex
|
||||
*
|
||||
* The default page_lock and i_size verification done by non-DAX fault paths
|
||||
* is sufficient because ext2 doesn't support hole punching.
|
||||
*/
|
||||
static vm_fault_t ext2_dax_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||
vm_fault_t ret;
|
||||
bool write = (vmf->flags & FAULT_FLAG_WRITE) &&
|
||||
(vmf->vma->vm_flags & VM_SHARED);
|
||||
|
||||
if (write) {
|
||||
sb_start_pagefault(inode->i_sb);
|
||||
file_update_time(vmf->vma->vm_file);
|
||||
}
|
||||
filemap_invalidate_lock_shared(inode->i_mapping);
|
||||
|
||||
ret = dax_iomap_fault(vmf, 0, NULL, NULL, &ext2_iomap_ops);
|
||||
|
||||
filemap_invalidate_unlock_shared(inode->i_mapping);
|
||||
if (write)
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct ext2_dax_vm_ops = {
|
||||
.fault = ext2_dax_fault,
|
||||
/*
|
||||
* .huge_fault is not supported for DAX because allocation in ext2
|
||||
* cannot be reliably aligned to huge page sizes and so pmd faults
|
||||
* will always fail and fail back to regular faults.
|
||||
*/
|
||||
.page_mkwrite = ext2_dax_fault,
|
||||
.pfn_mkwrite = ext2_dax_fault,
|
||||
};
|
||||
|
||||
static int ext2_file_mmap_prepare(struct vm_area_desc *desc)
|
||||
{
|
||||
struct file *file = desc->file;
|
||||
|
||||
if (!IS_DAX(file_inode(file)))
|
||||
return generic_file_mmap_prepare(desc);
|
||||
|
||||
file_accessed(file);
|
||||
desc->vm_ops = &ext2_dax_vm_ops;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define ext2_file_mmap_prepare generic_file_mmap_prepare
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called when filp is released. This happens when all file descriptors
|
||||
@@ -267,12 +161,15 @@ static ssize_t ext2_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
endbyte = pos + status - 1;
|
||||
ret2 = filemap_write_and_wait_range(inode->i_mapping, pos,
|
||||
endbyte);
|
||||
if (!ret2)
|
||||
if (!ret2) {
|
||||
invalidate_mapping_pages(inode->i_mapping,
|
||||
pos >> PAGE_SHIFT,
|
||||
endbyte >> PAGE_SHIFT);
|
||||
if (ret > 0)
|
||||
generic_write_sync(iocb, ret);
|
||||
if (ret > 0)
|
||||
ret = generic_write_sync(iocb, ret);
|
||||
} else {
|
||||
ret = ret2;
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
@@ -285,10 +182,6 @@ static ssize_t ext2_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
|
||||
static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
#ifdef CONFIG_FS_DAX
|
||||
if (IS_DAX(iocb->ki_filp->f_mapping->host))
|
||||
return ext2_dax_read_iter(iocb, to);
|
||||
#endif
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return ext2_dio_read_iter(iocb, to);
|
||||
|
||||
@@ -297,10 +190,6 @@ static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
|
||||
static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
#ifdef CONFIG_FS_DAX
|
||||
if (IS_DAX(iocb->ki_filp->f_mapping->host))
|
||||
return ext2_dax_write_iter(iocb, from);
|
||||
#endif
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return ext2_dio_write_iter(iocb, from);
|
||||
|
||||
@@ -321,7 +210,7 @@ const struct file_operations ext2_file_operations = {
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ext2_compat_ioctl,
|
||||
#endif
|
||||
.mmap_prepare = ext2_file_mmap_prepare,
|
||||
.mmap_prepare = generic_file_mmap_prepare,
|
||||
.open = ext2_file_open,
|
||||
.release = ext2_release_file,
|
||||
.fsync = ext2_fsync,
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dax.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/writeback.h>
|
||||
@@ -741,27 +740,6 @@ static int ext2_get_blocks(struct inode *inode,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (IS_DAX(inode)) {
|
||||
/*
|
||||
* We must unmap blocks before zeroing so that writeback cannot
|
||||
* overwrite zeros with stale data from block device page cache.
|
||||
*/
|
||||
clean_bdev_aliases(inode->i_sb->s_bdev,
|
||||
le32_to_cpu(chain[depth-1].key),
|
||||
count);
|
||||
/*
|
||||
* block must be initialised before we put it in the tree
|
||||
* so that it's not found by another thread before it's
|
||||
* initialised
|
||||
*/
|
||||
err = sb_issue_zeroout(inode->i_sb,
|
||||
le32_to_cpu(chain[depth-1].key), count,
|
||||
GFP_KERNEL);
|
||||
if (err) {
|
||||
mutex_unlock(&ei->truncate_mutex);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
*new = true;
|
||||
|
||||
ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
|
||||
@@ -811,7 +789,6 @@ static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
unsigned int blkbits = inode->i_blkbits;
|
||||
unsigned long first_block = offset >> blkbits;
|
||||
unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits;
|
||||
struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb);
|
||||
bool new = false, boundary = false;
|
||||
u32 bno;
|
||||
int ret;
|
||||
@@ -841,10 +818,7 @@ static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
|
||||
iomap->flags = 0;
|
||||
iomap->offset = (u64)first_block << blkbits;
|
||||
if (flags & IOMAP_DAX)
|
||||
iomap->dax_dev = sbi->s_daxdev;
|
||||
else
|
||||
iomap->bdev = inode->i_sb->s_bdev;
|
||||
iomap->bdev = inode->i_sb->s_bdev;
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
@@ -859,8 +833,6 @@ static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
} else {
|
||||
iomap->type = IOMAP_MAPPED;
|
||||
iomap->addr = (u64)bno << blkbits;
|
||||
if (flags & IOMAP_DAX)
|
||||
iomap->addr += sbi->s_dax_part_off;
|
||||
iomap->length = (u64)ret << blkbits;
|
||||
iomap->flags |= IOMAP_F_MERGED;
|
||||
}
|
||||
@@ -962,13 +934,6 @@ ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
||||
return mpage_writepages(mapping, wbc, ext2_get_block);
|
||||
}
|
||||
|
||||
static int
|
||||
ext2_dax_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
||||
{
|
||||
struct ext2_sb_info *sbi = EXT2_SB(mapping->host->i_sb);
|
||||
|
||||
return dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc);
|
||||
}
|
||||
|
||||
const struct address_space_operations ext2_aops = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
@@ -984,10 +949,6 @@ const struct address_space_operations ext2_aops = {
|
||||
.error_remove_folio = generic_error_remove_folio,
|
||||
};
|
||||
|
||||
static const struct address_space_operations ext2_dax_aops = {
|
||||
.writepages = ext2_dax_writepages,
|
||||
.dirty_folio = noop_dirty_folio,
|
||||
};
|
||||
|
||||
/*
|
||||
* Probably it should be a library function... search for first non-zero word
|
||||
@@ -1186,9 +1147,6 @@ static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
|
||||
blocksize = inode->i_sb->s_blocksize;
|
||||
iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
|
||||
|
||||
#ifdef CONFIG_FS_DAX
|
||||
WARN_ON(!rwsem_is_locked(&inode->i_mapping->invalidate_lock));
|
||||
#endif
|
||||
|
||||
n = ext2_block_to_path(inode, iblock, offsets, NULL);
|
||||
if (n == 0)
|
||||
@@ -1290,12 +1248,7 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
|
||||
|
||||
inode_dio_wait(inode);
|
||||
|
||||
if (IS_DAX(inode))
|
||||
error = dax_truncate_page(inode, newsize, NULL,
|
||||
&ext2_iomap_ops);
|
||||
else
|
||||
error = block_truncate_page(inode->i_mapping,
|
||||
newsize, ext2_get_block);
|
||||
error = block_truncate_page(inode->i_mapping, newsize, ext2_get_block);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -1363,7 +1316,7 @@ void ext2_set_inode_flags(struct inode *inode)
|
||||
unsigned int flags = EXT2_I(inode)->i_flags;
|
||||
|
||||
inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
|
||||
S_DIRSYNC | S_DAX);
|
||||
S_DIRSYNC);
|
||||
if (flags & EXT2_SYNC_FL)
|
||||
inode->i_flags |= S_SYNC;
|
||||
if (flags & EXT2_APPEND_FL)
|
||||
@@ -1374,18 +1327,13 @@ void ext2_set_inode_flags(struct inode *inode)
|
||||
inode->i_flags |= S_NOATIME;
|
||||
if (flags & EXT2_DIRSYNC_FL)
|
||||
inode->i_flags |= S_DIRSYNC;
|
||||
if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
|
||||
inode->i_flags |= S_DAX;
|
||||
}
|
||||
|
||||
void ext2_set_file_ops(struct inode *inode)
|
||||
{
|
||||
inode->i_op = &ext2_file_inode_operations;
|
||||
inode->i_fop = &ext2_file_operations;
|
||||
if (IS_DAX(inode))
|
||||
inode->i_mapping->a_ops = &ext2_dax_aops;
|
||||
else
|
||||
inode->i_mapping->a_ops = &ext2_aops;
|
||||
inode->i_mapping->a_ops = &ext2_aops;
|
||||
}
|
||||
|
||||
struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/dax.h>
|
||||
#include <linux/iversion.h>
|
||||
#include "ext2.h"
|
||||
#include "xattr.h"
|
||||
@@ -198,7 +197,6 @@ static void ext2_put_super (struct super_block * sb)
|
||||
brelse (sbi->s_sbh);
|
||||
sb->s_fs_info = NULL;
|
||||
kfree(sbi->s_blockgroup_lock);
|
||||
fs_put_dax(sbi->s_daxdev, NULL);
|
||||
kfree(sbi);
|
||||
}
|
||||
|
||||
@@ -329,11 +327,7 @@ static int ext2_show_options(struct seq_file *seq, struct dentry *root)
|
||||
if (test_opt(sb, GRPQUOTA))
|
||||
seq_puts(seq, ",grpquota");
|
||||
|
||||
if (test_opt(sb, XIP))
|
||||
seq_puts(seq, ",xip");
|
||||
|
||||
if (test_opt(sb, DAX))
|
||||
seq_puts(seq, ",dax");
|
||||
|
||||
if (!test_opt(sb, RESERVATION))
|
||||
seq_puts(seq, ",noreservation");
|
||||
@@ -596,18 +590,10 @@ static int ext2_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
break;
|
||||
#endif
|
||||
case Opt_xip:
|
||||
ext2_msg_fc(fc, KERN_INFO, "use dax instead of xip");
|
||||
ctx_set_mount_opt(ctx, EXT2_MOUNT_XIP);
|
||||
fallthrough;
|
||||
ext2_msg_fc(fc, KERN_WARNING, "DAX support has been removed. xip option ignored.");
|
||||
break;
|
||||
case Opt_dax:
|
||||
#ifdef CONFIG_FS_DAX
|
||||
ext2_msg_fc(fc, KERN_WARNING,
|
||||
"DAX enabled. Warning: DAX support in ext2 driver is deprecated"
|
||||
" and will be removed at the end of 2025. Please use ext4 driver instead.");
|
||||
ctx_set_mount_opt(ctx, EXT2_MOUNT_DAX);
|
||||
#else
|
||||
ext2_msg_fc(fc, KERN_INFO, "dax option not supported");
|
||||
#endif
|
||||
ext2_msg_fc(fc, KERN_WARNING, "DAX support has been removed. dax option ignored.");
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_QUOTA)
|
||||
@@ -906,8 +892,6 @@ static int ext2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
}
|
||||
sb->s_fs_info = sbi;
|
||||
sbi->s_sb_block = sb_block;
|
||||
sbi->s_daxdev = fs_dax_get_by_bdev(sb->s_bdev, &sbi->s_dax_part_off,
|
||||
NULL, NULL);
|
||||
|
||||
spin_lock_init(&sbi->s_lock);
|
||||
ret = -EINVAL;
|
||||
@@ -992,17 +976,6 @@ static int ext2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
}
|
||||
blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
|
||||
|
||||
if (test_opt(sb, DAX)) {
|
||||
if (!sbi->s_daxdev) {
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"DAX unsupported by block device. Turning off DAX.");
|
||||
clear_opt(sbi->s_mount_opt, DAX);
|
||||
} else if (blocksize != PAGE_SIZE) {
|
||||
ext2_msg(sb, KERN_ERR, "unsupported blocksize for DAX\n");
|
||||
clear_opt(sbi->s_mount_opt, DAX);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the blocksize doesn't match, re-read the thing.. */
|
||||
if (sb->s_blocksize != blocksize) {
|
||||
brelse(bh);
|
||||
@@ -1252,7 +1225,6 @@ static int ext2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
failed_mount:
|
||||
brelse(bh);
|
||||
failed_sbi:
|
||||
fs_put_dax(sbi->s_daxdev, NULL);
|
||||
sb->s_fs_info = NULL;
|
||||
kfree(sbi->s_blockgroup_lock);
|
||||
kfree(sbi);
|
||||
@@ -1379,11 +1351,6 @@ static int ext2_reconfigure(struct fs_context *fc)
|
||||
|
||||
spin_lock(&sbi->s_lock);
|
||||
es = sbi->s_es;
|
||||
if ((sbi->s_mount_opt ^ new_opts.s_mount_opt) & EXT2_MOUNT_DAX) {
|
||||
ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
|
||||
"dax flag with busy inodes while remounting");
|
||||
new_opts.s_mount_opt ^= EXT2_MOUNT_DAX;
|
||||
}
|
||||
if ((bool)(flags & SB_RDONLY) == sb_rdonly(sb))
|
||||
goto out_set;
|
||||
if (flags & SB_RDONLY) {
|
||||
|
||||
@@ -466,6 +466,9 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
|
||||
inode->i_size = symlink_len;
|
||||
while (slen > 1) {
|
||||
rootflag = 0;
|
||||
/* keep the component within the SL record */
|
||||
if (slp->len + 2 > slen)
|
||||
goto eio;
|
||||
switch (slp->flags & ~1) {
|
||||
case 0:
|
||||
inode->i_size +=
|
||||
@@ -621,6 +624,14 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
|
||||
slp = &rr->u.SL.link;
|
||||
while (slen > 1) {
|
||||
rootflag = 0;
|
||||
/*
|
||||
* A component is slp->len + 2 bytes (a two-byte header plus
|
||||
* len bytes of text). If it does not fit in the bytes left in
|
||||
* the SL record the record is malformed: fail like the plimit
|
||||
* checks below so readlink() returns -EIO, not a truncated path.
|
||||
*/
|
||||
if (slp->len + 2 > slen)
|
||||
return NULL;
|
||||
switch (slp->flags & ~1) {
|
||||
case 0:
|
||||
if (slp->len > plimit - rpnt)
|
||||
|
||||
@@ -82,8 +82,9 @@ static int load_block_bitmap(struct super_block *sb,
|
||||
int nr_groups = bitmap->s_nr_groups;
|
||||
|
||||
if (block_group >= nr_groups) {
|
||||
udf_debug("block_group (%u) > nr_groups (%d)\n",
|
||||
udf_debug("block_group (%u) >= nr_groups (%d)\n",
|
||||
block_group, nr_groups);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (bitmap->s_block_bitmap[block_group]) {
|
||||
@@ -662,7 +663,7 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode,
|
||||
|
||||
if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) ||
|
||||
check_add_overflow(blk, count, &blk) ||
|
||||
bloc->logicalBlockNum + count > map->s_partition_len) {
|
||||
blk > map->s_partition_len) {
|
||||
udf_debug("Invalid request to free blocks: (%d, %u), off %u, "
|
||||
"len %u, partition len %u\n",
|
||||
partition, bloc->logicalBlockNum, offset, count,
|
||||
|
||||
@@ -1242,6 +1242,11 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
|
||||
|
||||
if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
|
||||
map->s_type_specific.s_virtual.s_start_offset = 0;
|
||||
if (sbi->s_vat_inode->i_size < 36) {
|
||||
udf_err(sb, "Too short VAT inode size %lld\n",
|
||||
sbi->s_vat_inode->i_size);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
map->s_type_specific.s_virtual.s_num_entries =
|
||||
(sbi->s_vat_inode->i_size - 36) >> 2;
|
||||
} else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
|
||||
@@ -1263,6 +1268,14 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
|
||||
|
||||
map->s_type_specific.s_virtual.s_start_offset =
|
||||
le16_to_cpu(vat20->lengthHeader);
|
||||
if (map->s_type_specific.s_virtual.s_start_offset
|
||||
> sbi->s_vat_inode->i_size) {
|
||||
udf_err(sb, "Corrupted VAT header length %u (VAT inode size %lld)\n",
|
||||
map->s_type_specific.s_virtual.s_start_offset,
|
||||
sbi->s_vat_inode->i_size);
|
||||
brelse(bh);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
map->s_type_specific.s_virtual.s_num_entries =
|
||||
(sbi->s_vat_inode->i_size -
|
||||
map->s_type_specific.s_virtual.
|
||||
@@ -1418,7 +1431,8 @@ static int udf_load_sparable_map(struct super_block *sb,
|
||||
if (ident != 0 ||
|
||||
strncmp(st->sparingIdent.ident, UDF_ID_SPARING,
|
||||
strlen(UDF_ID_SPARING)) ||
|
||||
sizeof(*st) + le16_to_cpu(st->reallocationTableLen) >
|
||||
struct_size(st, mapEntry,
|
||||
le16_to_cpu(st->reallocationTableLen)) >
|
||||
sb->s_blocksize) {
|
||||
brelse(bh);
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user