Skip to content

Commit 3d85d6c

Browse files
committed
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
2 parents 2a1944b + b579910 commit 3d85d6c

File tree

11 files changed

+46
-21
lines changed

11 files changed

+46
-21
lines changed

fs/fuse/dev.c

+6
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,12 @@ static int fuse_check_folio(struct folio *folio)
838838
return 0;
839839
}
840840

841+
/*
842+
* Attempt to steal a page from the splice() pipe and move it into the
843+
* pagecache. If successful, the pointer in @pagep will be updated. The
844+
* folio that was originally in @pagep will lose a reference and the new
845+
* folio returned in @pagep will carry a reference.
846+
*/
841847
static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
842848
{
843849
int err;

fs/fuse/dir.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1636,7 +1636,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
16361636
goto out_err;
16371637

16381638
if (fc->cache_symlinks)
1639-
return page_get_link(dentry, inode, callback);
1639+
return page_get_link_raw(dentry, inode, callback);
16401640

16411641
err = -ECHILD;
16421642
if (!dentry)

fs/fuse/file.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,10 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
955955
fuse_invalidate_atime(inode);
956956
}
957957

958-
for (i = 0; i < ap->num_folios; i++)
958+
for (i = 0; i < ap->num_folios; i++) {
959959
folio_end_read(ap->folios[i], !err);
960+
folio_put(ap->folios[i]);
961+
}
960962
if (ia->ff)
961963
fuse_file_put(ia->ff, false);
962964

@@ -1048,7 +1050,14 @@ static void fuse_readahead(struct readahead_control *rac)
10481050
ap = &ia->ap;
10491051

10501052
while (ap->num_folios < cur_pages) {
1051-
folio = readahead_folio(rac);
1053+
/*
1054+
* This returns a folio with a ref held on it.
1055+
* The ref needs to be held until the request is
1056+
* completed, since the splice case (see
1057+
* fuse_try_move_page()) drops the ref after it's
1058+
* replaced in the page cache.
1059+
*/
1060+
folio = __readahead_folio(rac);
10521061
ap->folios[ap->num_folios] = folio;
10531062
ap->descs[ap->num_folios].length = folio_size(folio);
10541063
ap->num_folios++;

fs/iomap/direct-io.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -427,12 +427,10 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
427427
bio_put(bio);
428428
goto zero_tail;
429429
}
430-
if (dio->flags & IOMAP_DIO_WRITE) {
430+
if (dio->flags & IOMAP_DIO_WRITE)
431431
task_io_account_write(n);
432-
} else {
433-
if (dio->flags & IOMAP_DIO_DIRTY)
434-
bio_set_pages_dirty(bio);
435-
}
432+
else if (dio->flags & IOMAP_DIO_DIRTY)
433+
bio_set_pages_dirty(bio);
436434

437435
dio->size += n;
438436
copied += n;

fs/namei.c

+19-5
Original file line numberDiff line numberDiff line change
@@ -5356,10 +5356,9 @@ const char *vfs_get_link(struct dentry *dentry, struct delayed_call *done)
53565356
EXPORT_SYMBOL(vfs_get_link);
53575357

53585358
/* get the link contents into pagecache */
5359-
const char *page_get_link(struct dentry *dentry, struct inode *inode,
5360-
struct delayed_call *callback)
5359+
static char *__page_get_link(struct dentry *dentry, struct inode *inode,
5360+
struct delayed_call *callback)
53615361
{
5362-
char *kaddr;
53635362
struct page *page;
53645363
struct address_space *mapping = inode->i_mapping;
53655364

@@ -5378,8 +5377,23 @@ const char *page_get_link(struct dentry *dentry, struct inode *inode,
53785377
}
53795378
set_delayed_call(callback, page_put_link, page);
53805379
BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
5381-
kaddr = page_address(page);
5382-
nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
5380+
return page_address(page);
5381+
}
5382+
5383+
const char *page_get_link_raw(struct dentry *dentry, struct inode *inode,
5384+
struct delayed_call *callback)
5385+
{
5386+
return __page_get_link(dentry, inode, callback);
5387+
}
5388+
EXPORT_SYMBOL_GPL(page_get_link_raw);
5389+
5390+
const char *page_get_link(struct dentry *dentry, struct inode *inode,
5391+
struct delayed_call *callback)
5392+
{
5393+
char *kaddr = __page_get_link(dentry, inode, callback);
5394+
5395+
if (!IS_ERR(kaddr))
5396+
nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
53835397
return kaddr;
53845398
}
53855399

fs/nsfs.c

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
3737
}
3838

3939
const struct dentry_operations ns_dentry_operations = {
40-
.d_delete = always_delete_dentry,
4140
.d_dname = ns_dname,
4241
.d_prune = stashed_dentry_prune,
4342
};

fs/overlayfs/copy_up.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -618,14 +618,14 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
618618
err = PTR_ERR(upper);
619619
if (!IS_ERR(upper)) {
620620
err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
621-
dput(upper);
622621

623622
if (!err) {
624623
/* Restore timestamps on parent (best effort) */
625624
ovl_set_timestamps(ofs, upperdir, &c->pstat);
626625
ovl_dentry_set_upper_alias(c->dentry);
627626
ovl_dentry_update_reval(c->dentry, upper);
628627
}
628+
dput(upper);
629629
}
630630
inode_unlock(udir);
631631
if (err)

fs/pidfs.c

-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,6 @@ static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
521521
}
522522

523523
const struct dentry_operations pidfs_dentry_operations = {
524-
.d_delete = always_delete_dentry,
525524
.d_dname = pidfs_dname,
526525
.d_prune = stashed_dentry_prune,
527526
};

include/linux/fs.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -2975,8 +2975,8 @@ static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)
29752975
} else if (iocb->ki_flags & IOCB_DONTCACHE) {
29762976
struct address_space *mapping = iocb->ki_filp->f_mapping;
29772977

2978-
filemap_fdatawrite_range_kick(mapping, iocb->ki_pos,
2979-
iocb->ki_pos + count);
2978+
filemap_fdatawrite_range_kick(mapping, iocb->ki_pos - count,
2979+
iocb->ki_pos - 1);
29802980
}
29812981

29822982
return count;
@@ -3452,6 +3452,8 @@ extern const struct file_operations generic_ro_fops;
34523452

34533453
extern int readlink_copy(char __user *, int, const char *, int);
34543454
extern int page_readlink(struct dentry *, char __user *, int);
3455+
extern const char *page_get_link_raw(struct dentry *, struct inode *,
3456+
struct delayed_call *);
34553457
extern const char *page_get_link(struct dentry *, struct inode *,
34563458
struct delayed_call *);
34573459
extern void page_put_link(void *);

mm/filemap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ EXPORT_SYMBOL(filemap_fdatawrite_range);
445445
* filemap_fdatawrite_range_kick - start writeback on a range
446446
* @mapping: target address_space
447447
* @start: index to start writeback on
448-
* @end: last (non-inclusive) index for writeback
448+
* @end: last (inclusive) index for writeback
449449
*
450450
* This is a non-integrity writeback helper, to start writing back folios
451451
* for the indicated range.

mm/truncate.c

-2
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,6 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
548548

549549
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
550550

551-
if (folio_test_dirty(folio))
552-
return 0;
553551
if (folio_mapped(folio))
554552
unmap_mapping_folio(folio);
555553
BUG_ON(folio_mapped(folio));

0 commit comments

Comments
 (0)