vfs-6.14-rc5.fixes
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZ72tGgAKCRCRxhvAZXjc ovLnAQCbSaNoTmAHB45Au/3klYUL2MKS0COotj9SD4braLcMuAEApO4Ec+n+D+ky dylGZoKNwSZCY2fJmMykN199+QISsww= =LqgC -----END PGP SIGNATURE----- Merge tag 'vfs-6.14-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: - Use __readahead_folio() in fuse again to fix a UAF issue when using splice - Remove d_op->d_delete method from pidfs - Remove d_op->d_delete method from nsfs - Simplify iomap_dio_bio_iter() - Fix a UAF in ovl_dentry_update_reval - Fix a miscalulated file range for filemap_fdatawrite_range_kick() - Don't skip skip dirty page in folio_unmap_invalidate() * tag 'vfs-6.14-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: iomap: Minor code simplification in iomap_dio_bio_iter() nsfs: remove d_op->d_delete pidfs: remove d_op->d_delete mm/truncate: don't skip dirty page in folio_unmap_invalidate() mm/filemap: fix miscalculated file range for filemap_fdatawrite_range_kick() fuse: don't truncate cached, mutated symlink ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up fuse: revert back to __readahead_folio() for readahead
This commit is contained in:
commit
3d85d6c853
11 changed files with 46 additions and 21 deletions
|
@ -838,6 +838,12 @@ static int fuse_check_folio(struct folio *folio)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to steal a page from the splice() pipe and move it into the
|
||||||
|
* pagecache. If successful, the pointer in @pagep will be updated. The
|
||||||
|
* folio that was originally in @pagep will lose a reference and the new
|
||||||
|
* folio returned in @pagep will carry a reference.
|
||||||
|
*/
|
||||||
static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -1636,7 +1636,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
if (fc->cache_symlinks)
|
if (fc->cache_symlinks)
|
||||||
return page_get_link(dentry, inode, callback);
|
return page_get_link_raw(dentry, inode, callback);
|
||||||
|
|
||||||
err = -ECHILD;
|
err = -ECHILD;
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
|
|
|
@ -955,8 +955,10 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
|
||||||
fuse_invalidate_atime(inode);
|
fuse_invalidate_atime(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ap->num_folios; i++)
|
for (i = 0; i < ap->num_folios; i++) {
|
||||||
folio_end_read(ap->folios[i], !err);
|
folio_end_read(ap->folios[i], !err);
|
||||||
|
folio_put(ap->folios[i]);
|
||||||
|
}
|
||||||
if (ia->ff)
|
if (ia->ff)
|
||||||
fuse_file_put(ia->ff, false);
|
fuse_file_put(ia->ff, false);
|
||||||
|
|
||||||
|
@ -1048,7 +1050,14 @@ static void fuse_readahead(struct readahead_control *rac)
|
||||||
ap = &ia->ap;
|
ap = &ia->ap;
|
||||||
|
|
||||||
while (ap->num_folios < cur_pages) {
|
while (ap->num_folios < cur_pages) {
|
||||||
folio = readahead_folio(rac);
|
/*
|
||||||
|
* This returns a folio with a ref held on it.
|
||||||
|
* The ref needs to be held until the request is
|
||||||
|
* completed, since the splice case (see
|
||||||
|
* fuse_try_move_page()) drops the ref after it's
|
||||||
|
* replaced in the page cache.
|
||||||
|
*/
|
||||||
|
folio = __readahead_folio(rac);
|
||||||
ap->folios[ap->num_folios] = folio;
|
ap->folios[ap->num_folios] = folio;
|
||||||
ap->descs[ap->num_folios].length = folio_size(folio);
|
ap->descs[ap->num_folios].length = folio_size(folio);
|
||||||
ap->num_folios++;
|
ap->num_folios++;
|
||||||
|
|
|
@ -427,12 +427,10 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
goto zero_tail;
|
goto zero_tail;
|
||||||
}
|
}
|
||||||
if (dio->flags & IOMAP_DIO_WRITE) {
|
if (dio->flags & IOMAP_DIO_WRITE)
|
||||||
task_io_account_write(n);
|
task_io_account_write(n);
|
||||||
} else {
|
else if (dio->flags & IOMAP_DIO_DIRTY)
|
||||||
if (dio->flags & IOMAP_DIO_DIRTY)
|
bio_set_pages_dirty(bio);
|
||||||
bio_set_pages_dirty(bio);
|
|
||||||
}
|
|
||||||
|
|
||||||
dio->size += n;
|
dio->size += n;
|
||||||
copied += n;
|
copied += n;
|
||||||
|
|
24
fs/namei.c
24
fs/namei.c
|
@ -5356,10 +5356,9 @@ const char *vfs_get_link(struct dentry *dentry, struct delayed_call *done)
|
||||||
EXPORT_SYMBOL(vfs_get_link);
|
EXPORT_SYMBOL(vfs_get_link);
|
||||||
|
|
||||||
/* get the link contents into pagecache */
|
/* get the link contents into pagecache */
|
||||||
const char *page_get_link(struct dentry *dentry, struct inode *inode,
|
static char *__page_get_link(struct dentry *dentry, struct inode *inode,
|
||||||
struct delayed_call *callback)
|
struct delayed_call *callback)
|
||||||
{
|
{
|
||||||
char *kaddr;
|
|
||||||
struct page *page;
|
struct page *page;
|
||||||
struct address_space *mapping = inode->i_mapping;
|
struct address_space *mapping = inode->i_mapping;
|
||||||
|
|
||||||
|
@ -5378,8 +5377,23 @@ const char *page_get_link(struct dentry *dentry, struct inode *inode,
|
||||||
}
|
}
|
||||||
set_delayed_call(callback, page_put_link, page);
|
set_delayed_call(callback, page_put_link, page);
|
||||||
BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
|
BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
|
||||||
kaddr = page_address(page);
|
return page_address(page);
|
||||||
nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
|
}
|
||||||
|
|
||||||
|
const char *page_get_link_raw(struct dentry *dentry, struct inode *inode,
|
||||||
|
struct delayed_call *callback)
|
||||||
|
{
|
||||||
|
return __page_get_link(dentry, inode, callback);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(page_get_link_raw);
|
||||||
|
|
||||||
|
const char *page_get_link(struct dentry *dentry, struct inode *inode,
|
||||||
|
struct delayed_call *callback)
|
||||||
|
{
|
||||||
|
char *kaddr = __page_get_link(dentry, inode, callback);
|
||||||
|
|
||||||
|
if (!IS_ERR(kaddr))
|
||||||
|
nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
|
||||||
return kaddr;
|
return kaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct dentry_operations ns_dentry_operations = {
|
const struct dentry_operations ns_dentry_operations = {
|
||||||
.d_delete = always_delete_dentry,
|
|
||||||
.d_dname = ns_dname,
|
.d_dname = ns_dname,
|
||||||
.d_prune = stashed_dentry_prune,
|
.d_prune = stashed_dentry_prune,
|
||||||
};
|
};
|
||||||
|
|
|
@ -618,7 +618,6 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
|
||||||
err = PTR_ERR(upper);
|
err = PTR_ERR(upper);
|
||||||
if (!IS_ERR(upper)) {
|
if (!IS_ERR(upper)) {
|
||||||
err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
|
err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
|
||||||
dput(upper);
|
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
/* Restore timestamps on parent (best effort) */
|
/* Restore timestamps on parent (best effort) */
|
||||||
|
@ -626,6 +625,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
|
||||||
ovl_dentry_set_upper_alias(c->dentry);
|
ovl_dentry_set_upper_alias(c->dentry);
|
||||||
ovl_dentry_update_reval(c->dentry, upper);
|
ovl_dentry_update_reval(c->dentry, upper);
|
||||||
}
|
}
|
||||||
|
dput(upper);
|
||||||
}
|
}
|
||||||
inode_unlock(udir);
|
inode_unlock(udir);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -521,7 +521,6 @@ static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct dentry_operations pidfs_dentry_operations = {
|
const struct dentry_operations pidfs_dentry_operations = {
|
||||||
.d_delete = always_delete_dentry,
|
|
||||||
.d_dname = pidfs_dname,
|
.d_dname = pidfs_dname,
|
||||||
.d_prune = stashed_dentry_prune,
|
.d_prune = stashed_dentry_prune,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2975,8 +2975,8 @@ static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)
|
||||||
} else if (iocb->ki_flags & IOCB_DONTCACHE) {
|
} else if (iocb->ki_flags & IOCB_DONTCACHE) {
|
||||||
struct address_space *mapping = iocb->ki_filp->f_mapping;
|
struct address_space *mapping = iocb->ki_filp->f_mapping;
|
||||||
|
|
||||||
filemap_fdatawrite_range_kick(mapping, iocb->ki_pos,
|
filemap_fdatawrite_range_kick(mapping, iocb->ki_pos - count,
|
||||||
iocb->ki_pos + count);
|
iocb->ki_pos - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -3452,6 +3452,8 @@ extern const struct file_operations generic_ro_fops;
|
||||||
|
|
||||||
extern int readlink_copy(char __user *, int, const char *, int);
|
extern int readlink_copy(char __user *, int, const char *, int);
|
||||||
extern int page_readlink(struct dentry *, char __user *, int);
|
extern int page_readlink(struct dentry *, char __user *, int);
|
||||||
|
extern const char *page_get_link_raw(struct dentry *, struct inode *,
|
||||||
|
struct delayed_call *);
|
||||||
extern const char *page_get_link(struct dentry *, struct inode *,
|
extern const char *page_get_link(struct dentry *, struct inode *,
|
||||||
struct delayed_call *);
|
struct delayed_call *);
|
||||||
extern void page_put_link(void *);
|
extern void page_put_link(void *);
|
||||||
|
|
|
@ -445,7 +445,7 @@ EXPORT_SYMBOL(filemap_fdatawrite_range);
|
||||||
* filemap_fdatawrite_range_kick - start writeback on a range
|
* filemap_fdatawrite_range_kick - start writeback on a range
|
||||||
* @mapping: target address_space
|
* @mapping: target address_space
|
||||||
* @start: index to start writeback on
|
* @start: index to start writeback on
|
||||||
* @end: last (non-inclusive) index for writeback
|
* @end: last (inclusive) index for writeback
|
||||||
*
|
*
|
||||||
* This is a non-integrity writeback helper, to start writing back folios
|
* This is a non-integrity writeback helper, to start writing back folios
|
||||||
* for the indicated range.
|
* for the indicated range.
|
||||||
|
|
|
@ -548,8 +548,6 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
|
||||||
|
|
||||||
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
|
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
|
||||||
|
|
||||||
if (folio_test_dirty(folio))
|
|
||||||
return 0;
|
|
||||||
if (folio_mapped(folio))
|
if (folio_mapped(folio))
|
||||||
unmap_mapping_folio(folio);
|
unmap_mapping_folio(folio);
|
||||||
BUG_ON(folio_mapped(folio));
|
BUG_ON(folio_mapped(folio));
|
||||||
|
|
Loading…
Add table
Reference in a new issue