mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
Saner handling of "lseek should fail with ESPIPE" - gets rid of
magical no_llseek thing and makes checks consistent. In particular, ad-hoc "can we do splice via internal pipe" checks got saner (and somewhat more permissive, which is what Jason had been after, AFAICT) Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQqUNBr3gm4hGXdBJlZ7Krx/gZQ6wUCYug2xgAKCRBZ7Krx/gZQ 6wxWAQDqeg+xMq2FGPXmgjCa+Cp3PXH96Lp6f3hHzakIDx+t8gEAxvuiXAD22Mct 6S1SKuGj0iDIuM4L7hUiWTiY/bDXSAc= =3EC/ -----END PGP SIGNATURE----- Merge tag 'pull-work.lseek' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs Pull vfs lseek updates from Al Viro: "Jason's lseek series. Saner handling of 'lseek should fail with ESPIPE' - this gets rid of the magical no_llseek thing and makes checks consistent. In particular, the ad-hoc "can we do splice via internal pipe" checks got saner (and somewhat more permissive, which is what Jason had been after, AFAICT)" * tag 'pull-work.lseek' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fs: remove no_llseek fs: check FMODE_LSEEK to control internal pipe splicing vfio: do not set FMODE_LSEEK flag dma-buf: remove useless FMODE_LSEEK flag fs: do not compare against ->llseek fs: clear or set FMODE_LSEEK based on llseek function
This commit is contained in:
commit
a782e86649
12 changed files with 26 additions and 31 deletions
|
@ -914,3 +914,11 @@ Calling conventions for file_open_root() changed; now it takes struct path *
|
||||||
instead of passing mount and dentry separately. For callers that used to
|
instead of passing mount and dentry separately. For callers that used to
|
||||||
pass <mnt, mnt->mnt_root> pair (i.e. the root of given mount), a new helper
|
pass <mnt, mnt->mnt_root> pair (i.e. the root of given mount), a new helper
|
||||||
is provided - file_open_root_mnt(). In-tree users adjusted.
|
is provided - file_open_root_mnt(). In-tree users adjusted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**mandatory**
|
||||||
|
|
||||||
|
no_llseek is gone; don't set .llseek to that - just leave it NULL instead.
|
||||||
|
Checks for "does that file have llseek(2), or should it fail with ESPIPE"
|
||||||
|
should be done by looking at FMODE_LSEEK in file->f_mode.
|
||||||
|
|
|
@ -549,7 +549,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|
||||||
goto err_dmabuf;
|
goto err_dmabuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->f_mode |= FMODE_LSEEK;
|
|
||||||
dmabuf->file = file;
|
dmabuf->file = file;
|
||||||
|
|
||||||
mutex_init(&dmabuf->lock);
|
mutex_init(&dmabuf->lock);
|
||||||
|
|
|
@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal);
|
||||||
* Since events are used by the KMS API for vblank and page flip completion this
|
* Since events are used by the KMS API for vblank and page flip completion this
|
||||||
* means all modern display drivers must use it.
|
* means all modern display drivers must use it.
|
||||||
*
|
*
|
||||||
* @offset is ignored, DRM events are read like a pipe. Therefore drivers also
|
* @offset is ignored, DRM events are read like a pipe. Polling support is
|
||||||
* must set the &file_operation.llseek to no_llseek(). Polling support is
|
|
||||||
* provided by drm_poll().
|
* provided by drm_poll().
|
||||||
*
|
*
|
||||||
* This function will only ever read a full event. Therefore userspace must
|
* This function will only ever read a full event. Therefore userspace must
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ static struct file *vfio_device_open(struct vfio_device *device)
|
||||||
* Appears to be missing by lack of need rather than
|
* Appears to be missing by lack of need rather than
|
||||||
* explicitly prevented. Now there's need.
|
* explicitly prevented. Now there's need.
|
||||||
*/
|
*/
|
||||||
filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
filep->f_mode |= (FMODE_PREAD | FMODE_PWRITE);
|
||||||
|
|
||||||
if (device->group->type == VFIO_NO_IOMMU)
|
if (device->group->type == VFIO_NO_IOMMU)
|
||||||
dev_warn(device->dev, "vfio-noiommu device opened by user "
|
dev_warn(device->dev, "vfio-noiommu device opened by user "
|
||||||
|
|
|
@ -816,9 +816,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
|
||||||
{
|
{
|
||||||
static char zeroes[PAGE_SIZE];
|
static char zeroes[PAGE_SIZE];
|
||||||
struct file *file = cprm->file;
|
struct file *file = cprm->file;
|
||||||
if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
|
if (file->f_mode & FMODE_LSEEK) {
|
||||||
if (dump_interrupted() ||
|
if (dump_interrupted() ||
|
||||||
file->f_op->llseek(file, nr, SEEK_CUR) < 0)
|
vfs_llseek(file, nr, SEEK_CUR) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
cprm->pos += nr;
|
cprm->pos += nr;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -235,6 +235,8 @@ static struct file *alloc_file(const struct path *path, int flags,
|
||||||
file->f_mapping = path->dentry->d_inode->i_mapping;
|
file->f_mapping = path->dentry->d_inode->i_mapping;
|
||||||
file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
|
file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
|
||||||
file->f_sb_err = file_sample_sb_err(file);
|
file->f_sb_err = file_sample_sb_err(file);
|
||||||
|
if (fop->llseek)
|
||||||
|
file->f_mode |= FMODE_LSEEK;
|
||||||
if ((file->f_mode & FMODE_READ) &&
|
if ((file->f_mode & FMODE_READ) &&
|
||||||
likely(fop->read || fop->read_iter))
|
likely(fop->read || fop->read_iter))
|
||||||
file->f_mode |= FMODE_CAN_READ;
|
file->f_mode |= FMODE_CAN_READ;
|
||||||
|
|
|
@ -888,6 +888,8 @@ static int do_dentry_open(struct file *f,
|
||||||
if ((f->f_mode & FMODE_WRITE) &&
|
if ((f->f_mode & FMODE_WRITE) &&
|
||||||
likely(f->f_op->write || f->f_op->write_iter))
|
likely(f->f_op->write || f->f_op->write_iter))
|
||||||
f->f_mode |= FMODE_CAN_WRITE;
|
f->f_mode |= FMODE_CAN_WRITE;
|
||||||
|
if ((f->f_mode & FMODE_LSEEK) && !f->f_op->llseek)
|
||||||
|
f->f_mode &= ~FMODE_LSEEK;
|
||||||
if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
|
if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
|
||||||
f->f_mode |= FMODE_CAN_ODIRECT;
|
f->f_mode |= FMODE_CAN_ODIRECT;
|
||||||
|
|
||||||
|
|
|
@ -226,8 +226,7 @@ static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old,
|
||||||
/* Couldn't clone, so now we try to copy the data */
|
/* Couldn't clone, so now we try to copy the data */
|
||||||
|
|
||||||
/* Check if lower fs supports seek operation */
|
/* Check if lower fs supports seek operation */
|
||||||
if (old_file->f_mode & FMODE_LSEEK &&
|
if (old_file->f_mode & FMODE_LSEEK)
|
||||||
old_file->f_op->llseek)
|
|
||||||
skip_hole = true;
|
skip_hole = true;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
|
|
|
@ -227,12 +227,6 @@ loff_t noop_llseek(struct file *file, loff_t offset, int whence)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(noop_llseek);
|
EXPORT_SYMBOL(noop_llseek);
|
||||||
|
|
||||||
loff_t no_llseek(struct file *file, loff_t offset, int whence)
|
|
||||||
{
|
|
||||||
return -ESPIPE;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(no_llseek);
|
|
||||||
|
|
||||||
loff_t default_llseek(struct file *file, loff_t offset, int whence)
|
loff_t default_llseek(struct file *file, loff_t offset, int whence)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
|
@ -290,14 +284,9 @@ EXPORT_SYMBOL(default_llseek);
|
||||||
|
|
||||||
loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
|
loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
|
||||||
{
|
{
|
||||||
loff_t (*fn)(struct file *, loff_t, int);
|
if (!(file->f_mode & FMODE_LSEEK))
|
||||||
|
return -ESPIPE;
|
||||||
fn = no_llseek;
|
return file->f_op->llseek(file, offset, whence);
|
||||||
if (file->f_mode & FMODE_LSEEK) {
|
|
||||||
if (file->f_op->llseek)
|
|
||||||
fn = file->f_op->llseek;
|
|
||||||
}
|
|
||||||
return fn(file, offset, whence);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vfs_llseek);
|
EXPORT_SYMBOL(vfs_llseek);
|
||||||
|
|
||||||
|
|
10
fs/splice.c
10
fs/splice.c
|
@ -814,17 +814,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
|
||||||
{
|
{
|
||||||
struct pipe_inode_info *pipe;
|
struct pipe_inode_info *pipe;
|
||||||
long ret, bytes;
|
long ret, bytes;
|
||||||
umode_t i_mode;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
int i, flags, more;
|
int i, flags, more;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We require the input being a regular file, as we don't want to
|
* We require the input to be seekable, as we don't want to randomly
|
||||||
* randomly drop data for eg socket -> socket splicing. Use the
|
* drop data for eg socket -> socket splicing. Use the piped splicing
|
||||||
* piped splicing for that!
|
* for that!
|
||||||
*/
|
*/
|
||||||
i_mode = file_inode(in)->i_mode;
|
if (unlikely(!(in->f_mode & FMODE_LSEEK)))
|
||||||
if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3152,7 +3152,7 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
||||||
extern void
|
extern void
|
||||||
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
|
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
|
||||||
extern loff_t noop_llseek(struct file *file, loff_t offset, int whence);
|
extern loff_t noop_llseek(struct file *file, loff_t offset, int whence);
|
||||||
extern loff_t no_llseek(struct file *file, loff_t offset, int whence);
|
#define no_llseek NULL
|
||||||
extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
|
extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
|
||||||
extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
|
extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
|
||||||
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
|
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
|
||||||
|
|
|
@ -81,10 +81,9 @@ static bool bpf_iter_support_resched(struct seq_file *seq)
|
||||||
#define MAX_ITER_OBJECTS 1000000
|
#define MAX_ITER_OBJECTS 1000000
|
||||||
|
|
||||||
/* bpf_seq_read, a customized and simpler version for bpf iterator.
|
/* bpf_seq_read, a customized and simpler version for bpf iterator.
|
||||||
* no_llseek is assumed for this file.
|
|
||||||
* The following are differences from seq_read():
|
* The following are differences from seq_read():
|
||||||
* . fixed buffer size (PAGE_SIZE)
|
* . fixed buffer size (PAGE_SIZE)
|
||||||
* . assuming no_llseek
|
* . assuming NULL ->llseek()
|
||||||
* . stop() may call bpf program, handling potential overflow there
|
* . stop() may call bpf program, handling potential overflow there
|
||||||
*/
|
*/
|
||||||
static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,
|
static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,
|
||||||
|
|
Loading…
Add table
Reference in a new issue