mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 07:04:24 +00:00
Changes since last update:
- Fix return codes in erofs_fscache_{meta_,}read_folio error paths; - Fix potential wrong pcluster sizes for later non-4K lclusters; - Fix in-memory pcluster use-after-free on UP platforms. -----BEGIN PGP SIGNATURE----- iIcEABYIAC8WIQThPAmQN9sSA0DVxtI5NzHcH7XmBAUCYxdnPREceGlhbmdAa2Vy bmVsLm9yZwAKCRA5NzHcH7XmBGzxAQCvIteTLkD2HWvvflFcrby6o1vWxoJSDFig J3QZUgH/TAEAvR6Jyl4oL4/kwtw+2ZuWeXnMI9FXBfz9pyDR/MiCQQw= =p6+J -----END PGP SIGNATURE----- Merge tag 'erofs-for-6.0-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs Pull erofs fixes from Gao Xiang: - Fix return codes in erofs_fscache_{meta_,}read_folio error paths - Fix potential wrong pcluster sizes for later non-4K lclusters - Fix in-memory pcluster use-after-free on UP platforms * tag 'erofs-for-6.0-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: fix pcluster use-after-free on UP platforms erofs: avoid the potentially wrong m_plen for big pcluster erofs: fix error return code in erofs_fscache_{meta_,}read_folio
This commit is contained in:
commit
d2ec799d1c
3 changed files with 14 additions and 39 deletions
|
@ -222,8 +222,10 @@ static int erofs_fscache_meta_read_folio(struct file *data, struct folio *folio)
|
||||||
|
|
||||||
rreq = erofs_fscache_alloc_request(folio_mapping(folio),
|
rreq = erofs_fscache_alloc_request(folio_mapping(folio),
|
||||||
folio_pos(folio), folio_size(folio));
|
folio_pos(folio), folio_size(folio));
|
||||||
if (IS_ERR(rreq))
|
if (IS_ERR(rreq)) {
|
||||||
|
ret = PTR_ERR(rreq);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
|
return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
|
||||||
rreq, mdev.m_pa);
|
rreq, mdev.m_pa);
|
||||||
|
@ -301,8 +303,10 @@ static int erofs_fscache_read_folio(struct file *file, struct folio *folio)
|
||||||
|
|
||||||
rreq = erofs_fscache_alloc_request(folio_mapping(folio),
|
rreq = erofs_fscache_alloc_request(folio_mapping(folio),
|
||||||
folio_pos(folio), folio_size(folio));
|
folio_pos(folio), folio_size(folio));
|
||||||
if (IS_ERR(rreq))
|
if (IS_ERR(rreq)) {
|
||||||
|
ret = PTR_ERR(rreq);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
pstart = mdev.m_pa + (pos - map.m_la);
|
pstart = mdev.m_pa + (pos - map.m_la);
|
||||||
return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
|
return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
|
||||||
|
|
|
@ -195,7 +195,6 @@ struct erofs_workgroup {
|
||||||
atomic_t refcount;
|
atomic_t refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_SMP)
|
|
||||||
static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
|
static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
|
||||||
int val)
|
int val)
|
||||||
{
|
{
|
||||||
|
@ -224,34 +223,6 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
|
||||||
return atomic_cond_read_relaxed(&grp->refcount,
|
return atomic_cond_read_relaxed(&grp->refcount,
|
||||||
VAL != EROFS_LOCKED_MAGIC);
|
VAL != EROFS_LOCKED_MAGIC);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
|
|
||||||
int val)
|
|
||||||
{
|
|
||||||
preempt_disable();
|
|
||||||
/* no need to spin on UP platforms, let's just disable preemption. */
|
|
||||||
if (val != atomic_read(&grp->refcount)) {
|
|
||||||
preempt_enable();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
|
|
||||||
int orig_val)
|
|
||||||
{
|
|
||||||
preempt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
|
|
||||||
{
|
|
||||||
int v = atomic_read(&grp->refcount);
|
|
||||||
|
|
||||||
/* workgroup is never freezed on uniprocessor systems */
|
|
||||||
DBG_BUGON(v == EROFS_LOCKED_MAGIC);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_SMP */
|
|
||||||
#endif /* !CONFIG_EROFS_FS_ZIP */
|
#endif /* !CONFIG_EROFS_FS_ZIP */
|
||||||
|
|
||||||
/* we strictly follow PAGE_SIZE and no buffer head yet */
|
/* we strictly follow PAGE_SIZE and no buffer head yet */
|
||||||
|
|
|
@ -141,7 +141,7 @@ struct z_erofs_maprecorder {
|
||||||
u8 type, headtype;
|
u8 type, headtype;
|
||||||
u16 clusterofs;
|
u16 clusterofs;
|
||||||
u16 delta[2];
|
u16 delta[2];
|
||||||
erofs_blk_t pblk, compressedlcs;
|
erofs_blk_t pblk, compressedblks;
|
||||||
erofs_off_t nextpackoff;
|
erofs_off_t nextpackoff;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
|
||||||
DBG_BUGON(1);
|
DBG_BUGON(1);
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
}
|
}
|
||||||
m->compressedlcs = m->delta[0] &
|
m->compressedblks = m->delta[0] &
|
||||||
~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
||||||
m->delta[0] = 1;
|
m->delta[0] = 1;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||||
DBG_BUGON(1);
|
DBG_BUGON(1);
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
}
|
}
|
||||||
m->compressedlcs = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
m->compressedblks = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
||||||
m->delta[0] = 1;
|
m->delta[0] = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (i + 1 != (int)vcnt) {
|
} else if (i + 1 != (int)vcnt) {
|
||||||
|
@ -497,7 +497,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lcn = m->lcn + 1;
|
lcn = m->lcn + 1;
|
||||||
if (m->compressedlcs)
|
if (m->compressedblks)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = z_erofs_load_cluster_from_disk(m, lcn, false);
|
err = z_erofs_load_cluster_from_disk(m, lcn, false);
|
||||||
|
@ -506,7 +506,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the 1st NONHEAD lcluster has already been handled initially w/o
|
* If the 1st NONHEAD lcluster has already been handled initially w/o
|
||||||
* valid compressedlcs, which means at least it mustn't be CBLKCNT, or
|
* valid compressedblks, which means at least it mustn't be CBLKCNT, or
|
||||||
* an internal implemenatation error is detected.
|
* an internal implemenatation error is detected.
|
||||||
*
|
*
|
||||||
* The following code can also handle it properly anyway, but let's
|
* The following code can also handle it properly anyway, but let's
|
||||||
|
@ -523,12 +523,12 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||||
* if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
|
* if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
|
||||||
* rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
|
* rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
|
||||||
*/
|
*/
|
||||||
m->compressedlcs = 1;
|
m->compressedblks = 1 << (lclusterbits - LOG_BLOCK_SIZE);
|
||||||
break;
|
break;
|
||||||
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
||||||
if (m->delta[0] != 1)
|
if (m->delta[0] != 1)
|
||||||
goto err_bonus_cblkcnt;
|
goto err_bonus_cblkcnt;
|
||||||
if (m->compressedlcs)
|
if (m->compressedblks)
|
||||||
break;
|
break;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
default:
|
default:
|
||||||
|
@ -539,7 +539,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
map->m_plen = (u64)m->compressedlcs << lclusterbits;
|
map->m_plen = (u64)m->compressedblks << LOG_BLOCK_SIZE;
|
||||||
return 0;
|
return 0;
|
||||||
err_bonus_cblkcnt:
|
err_bonus_cblkcnt:
|
||||||
erofs_err(m->inode->i_sb,
|
erofs_err(m->inode->i_sb,
|
||||||
|
|
Loading…
Reference in a new issue