mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
\n
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAluGfbAACgkQnJ2qBz9k QNmkVQgAjv/tCHStwoQ4Hhr6q5wLU9apAW5WC7Or2MyNfqoJsKgyujpikwFMa0xY wkVqlITYavvUKl/nRlQ6hpZtAY7hi1Y7GvIYs2ci6QO4YAUuBoH7qPLKqyZYzXx+ mBaC68885nMMDqIHvsCcLurwTiDer6XQXXPDmpMoO9g4kyVuhm2e0/M7CPaA4Ue9 WEfBPBROSNdRH7Wtww/MUvtfd+9mezdlpUQZVVO5cdhAVQ8pzW2g2piYtwIpaY7E DiJ1zcgaqCnni+b69x4wz8TwB0q8wZJjrPfJgf4X7mIGBZrw80yNRlevfe5SxwdJ mkMDvjaD0TEItvpjgTZReXaAjFOWTA== =E61M -----END PGP SIGNATURE----- Merge tag 'for_v4.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs Pull misc fs fixes from Jan Kara: - make UDF to properly mount media created by Win7 - make isofs to properly refuse devices with large physical block size - fix a Spectre gadget in quotactl(2) - fix a warning in fsnotify code hit by syzkaller * tag 'for_v4.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: udf: Fix mounting of Win7 created UDF filesystems udf: Remove dead code from udf_find_fileset() fs/quota: Fix spectre gadget in do_quotactl fs/quota: Replace XQM_MAXQUOTAS usage with MAXQUOTAS isofs: reject hardware sector size > 2048 bytes fsnotify: fix false positive warning on inode delete
This commit is contained in:
commit
f3f106dac0
@ -24,6 +24,7 @@
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include "isofs.h"
|
||||
#include "zisofs.h"
|
||||
@ -653,6 +654,12 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
|
||||
/*
|
||||
* What if bugger tells us to go beyond page size?
|
||||
*/
|
||||
if (bdev_logical_block_size(s->s_bdev) > 2048) {
|
||||
printk(KERN_WARNING
|
||||
"ISOFS: unsupported/invalid hardware sector size %d\n",
|
||||
bdev_logical_block_size(s->s_bdev));
|
||||
goto out_freesbi;
|
||||
}
|
||||
opt.blocksize = sb_min_blocksize(s, opt.blocksize);
|
||||
|
||||
sbi->s_high_sierra = 0; /* default is iso9660 */
|
||||
|
@ -132,13 +132,13 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
|
||||
struct fsnotify_mark *mark;
|
||||
|
||||
assert_spin_locked(&conn->lock);
|
||||
/* We can get detached connector here when inode is getting unlinked. */
|
||||
if (!fsnotify_valid_obj_type(conn->type))
|
||||
return;
|
||||
hlist_for_each_entry(mark, &conn->list, obj_list) {
|
||||
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
|
||||
new_mask |= mark->mask;
|
||||
}
|
||||
if (WARN_ON(!fsnotify_valid_obj_type(conn->type)))
|
||||
return;
|
||||
|
||||
*fsnotify_conn_mask_p(conn) = new_mask;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
|
||||
qid_t id)
|
||||
@ -120,8 +121,6 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
|
||||
struct if_dqinfo uinfo;
|
||||
int ret;
|
||||
|
||||
/* This checks whether qc_state has enough entries... */
|
||||
BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS);
|
||||
if (!sb->s_qcop->get_state)
|
||||
return -ENOSYS;
|
||||
ret = sb->s_qcop->get_state(sb, &state);
|
||||
@ -354,10 +353,10 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
|
||||
* GETXSTATE quotactl has space for just one set of time limits so
|
||||
* report them for the first enabled quota type
|
||||
*/
|
||||
for (type = 0; type < XQM_MAXQUOTAS; type++)
|
||||
for (type = 0; type < MAXQUOTAS; type++)
|
||||
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
|
||||
break;
|
||||
BUG_ON(type == XQM_MAXQUOTAS);
|
||||
BUG_ON(type == MAXQUOTAS);
|
||||
fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
|
||||
fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
|
||||
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
|
||||
@ -427,10 +426,10 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
|
||||
* GETXSTATV quotactl has space for just one set of time limits so
|
||||
* report them for the first enabled quota type
|
||||
*/
|
||||
for (type = 0; type < XQM_MAXQUOTAS; type++)
|
||||
for (type = 0; type < MAXQUOTAS; type++)
|
||||
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
|
||||
break;
|
||||
BUG_ON(type == XQM_MAXQUOTAS);
|
||||
BUG_ON(type == MAXQUOTAS);
|
||||
fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
|
||||
fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
|
||||
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
|
||||
@ -701,8 +700,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
|
||||
if (type >= MAXQUOTAS)
|
||||
return -EINVAL;
|
||||
type = array_index_nospec(type, MAXQUOTAS);
|
||||
/*
|
||||
* Quota not supported on this fs? Check this before s_quota_types
|
||||
* since they needn't be set if quota is not supported at all.
|
||||
|
@ -764,9 +764,7 @@ static int udf_find_fileset(struct super_block *sb,
|
||||
struct kernel_lb_addr *root)
|
||||
{
|
||||
struct buffer_head *bh = NULL;
|
||||
long lastblock;
|
||||
uint16_t ident;
|
||||
struct udf_sb_info *sbi;
|
||||
|
||||
if (fileset->logicalBlockNum != 0xFFFFFFFF ||
|
||||
fileset->partitionReferenceNum != 0xFFFF) {
|
||||
@ -779,69 +777,11 @@ static int udf_find_fileset(struct super_block *sb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sbi = UDF_SB(sb);
|
||||
if (!bh) {
|
||||
/* Search backwards through the partitions */
|
||||
struct kernel_lb_addr newfileset;
|
||||
|
||||
/* --> cvg: FIXME - is it reasonable? */
|
||||
return 1;
|
||||
|
||||
for (newfileset.partitionReferenceNum = sbi->s_partitions - 1;
|
||||
(newfileset.partitionReferenceNum != 0xFFFF &&
|
||||
fileset->logicalBlockNum == 0xFFFFFFFF &&
|
||||
fileset->partitionReferenceNum == 0xFFFF);
|
||||
newfileset.partitionReferenceNum--) {
|
||||
lastblock = sbi->s_partmaps
|
||||
[newfileset.partitionReferenceNum]
|
||||
.s_partition_len;
|
||||
newfileset.logicalBlockNum = 0;
|
||||
|
||||
do {
|
||||
bh = udf_read_ptagged(sb, &newfileset, 0,
|
||||
&ident);
|
||||
if (!bh) {
|
||||
newfileset.logicalBlockNum++;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ident) {
|
||||
case TAG_IDENT_SBD:
|
||||
{
|
||||
struct spaceBitmapDesc *sp;
|
||||
sp = (struct spaceBitmapDesc *)
|
||||
bh->b_data;
|
||||
newfileset.logicalBlockNum += 1 +
|
||||
((le32_to_cpu(sp->numOfBytes) +
|
||||
sizeof(struct spaceBitmapDesc)
|
||||
- 1) >> sb->s_blocksize_bits);
|
||||
brelse(bh);
|
||||
break;
|
||||
}
|
||||
case TAG_IDENT_FSD:
|
||||
*fileset = newfileset;
|
||||
break;
|
||||
default:
|
||||
newfileset.logicalBlockNum++;
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
break;
|
||||
}
|
||||
} while (newfileset.logicalBlockNum < lastblock &&
|
||||
fileset->logicalBlockNum == 0xFFFFFFFF &&
|
||||
fileset->partitionReferenceNum == 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
if ((fileset->logicalBlockNum != 0xFFFFFFFF ||
|
||||
fileset->partitionReferenceNum != 0xFFFF) && bh) {
|
||||
udf_debug("Fileset at block=%u, partition=%u\n",
|
||||
fileset->logicalBlockNum,
|
||||
fileset->partitionReferenceNum);
|
||||
|
||||
sbi->s_partition = fileset->partitionReferenceNum;
|
||||
UDF_SB(sb)->s_partition = fileset->partitionReferenceNum;
|
||||
udf_load_fileset(sb, bh, root);
|
||||
brelse(bh);
|
||||
return 0;
|
||||
@ -1570,10 +1510,16 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
|
||||
*/
|
||||
#define PART_DESC_ALLOC_STEP 32
|
||||
|
||||
struct part_desc_seq_scan_data {
|
||||
struct udf_vds_record rec;
|
||||
u32 partnum;
|
||||
};
|
||||
|
||||
struct desc_seq_scan_data {
|
||||
struct udf_vds_record vds[VDS_POS_LENGTH];
|
||||
unsigned int size_part_descs;
|
||||
struct udf_vds_record *part_descs_loc;
|
||||
unsigned int num_part_descs;
|
||||
struct part_desc_seq_scan_data *part_descs_loc;
|
||||
};
|
||||
|
||||
static struct udf_vds_record *handle_partition_descriptor(
|
||||
@ -1582,10 +1528,14 @@ static struct udf_vds_record *handle_partition_descriptor(
|
||||
{
|
||||
struct partitionDesc *desc = (struct partitionDesc *)bh->b_data;
|
||||
int partnum;
|
||||
int i;
|
||||
|
||||
partnum = le16_to_cpu(desc->partitionNumber);
|
||||
if (partnum >= data->size_part_descs) {
|
||||
struct udf_vds_record *new_loc;
|
||||
for (i = 0; i < data->num_part_descs; i++)
|
||||
if (partnum == data->part_descs_loc[i].partnum)
|
||||
return &(data->part_descs_loc[i].rec);
|
||||
if (data->num_part_descs >= data->size_part_descs) {
|
||||
struct part_desc_seq_scan_data *new_loc;
|
||||
unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
|
||||
|
||||
new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
|
||||
@ -1597,7 +1547,7 @@ static struct udf_vds_record *handle_partition_descriptor(
|
||||
data->part_descs_loc = new_loc;
|
||||
data->size_part_descs = new_size;
|
||||
}
|
||||
return &(data->part_descs_loc[partnum]);
|
||||
return &(data->part_descs_loc[data->num_part_descs++].rec);
|
||||
}
|
||||
|
||||
|
||||
@ -1647,6 +1597,7 @@ static noinline int udf_process_sequence(
|
||||
|
||||
memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
|
||||
data.size_part_descs = PART_DESC_ALLOC_STEP;
|
||||
data.num_part_descs = 0;
|
||||
data.part_descs_loc = kcalloc(data.size_part_descs,
|
||||
sizeof(*data.part_descs_loc),
|
||||
GFP_KERNEL);
|
||||
@ -1658,7 +1609,6 @@ static noinline int udf_process_sequence(
|
||||
* are in it.
|
||||
*/
|
||||
for (; (!done && block <= lastblock); block++) {
|
||||
|
||||
bh = udf_read_tagged(sb, block, block, &ident);
|
||||
if (!bh)
|
||||
break;
|
||||
@ -1730,13 +1680,10 @@ static noinline int udf_process_sequence(
|
||||
}
|
||||
|
||||
/* Now handle prevailing Partition Descriptors */
|
||||
for (i = 0; i < data.size_part_descs; i++) {
|
||||
if (data.part_descs_loc[i].block) {
|
||||
ret = udf_load_partdesc(sb,
|
||||
data.part_descs_loc[i].block);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < data.num_part_descs; i++) {
|
||||
ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -408,13 +408,7 @@ struct qc_type_state {
|
||||
|
||||
struct qc_state {
|
||||
unsigned int s_incoredqs; /* Number of dquots in core */
|
||||
/*
|
||||
* Per quota type information. The array should really have
|
||||
* max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in
|
||||
* quota_getinfo() makes sure XQM_MAXQUOTAS is large enough. Once VFS
|
||||
* supports project quotas, this can be changed to MAXQUOTAS
|
||||
*/
|
||||
struct qc_type_state s_state[XQM_MAXQUOTAS];
|
||||
struct qc_type_state s_state[MAXQUOTAS]; /* Per quota type information */
|
||||
};
|
||||
|
||||
/* Structure for communicating via ->set_info */
|
||||
|
Loading…
Reference in New Issue
Block a user