Re: Commit 0be0ee71 ("fs: properly and reliably lock f_pos in fdget_pos()") breaking userspace

From: Linus Torvalds
Date: Mon Nov 25 2019 - 17:55:45 EST


On Mon, Nov 25, 2019 at 1:30 PM Kenneth R. Crudup <kenny@xxxxxxxxx> wrote:
>
> FYI. Don't know if the fault lies with these subsystems or not, but I know
> it's been a goal to keep things working. In both cases, reverting this commit
> fixes both these issues. If you need additional information from me, please
> let me know.

Do you have any way to figure out what file descriptor we have in
those two cases?

It's almost certainly trivial to fix - if I were to know just what
kind of file we're blocking on that just needs to be marked
FMODE_STREAM.

The commit itself is also trivial enough to just revert if we can't
figure it out, but that's why I applied it first thing in the merge
window - to see the problems quickly and hopefully get them fixed. It
obviously showed no problems on my machines, but I have neither vmware
nor KDE upower...

Anyway, here's a TOTALLYT UNTESTED patch that may help pinpoint which
thing it is that causes issues.

It might also be so noisy as to be useless, I didn't think it through
a lot. Mind trying it out if you can't immediately see "ahh, vmware fd
#N is a file of type XYZ"?

Linus
fs/open.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/fs/open.c b/fs/open.c
index 5c68282ea79e..5dfe7cde4ff5 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1075,6 +1075,21 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
}
EXPORT_SYMBOL(file_open_root);

+/* Hacky hack hack */
+static void check_if_stream(struct file *f, const char *name)
+{
+ /* Already marked as FMODE_STREAM */
+ if (f->f_mode & FMODE_STREAM)
+ return;
+
+ /* Does it have a real lseek implementation? Not a stream */
+ if (f->f_op && f->f_op->llseek && f->f_op->llseek != no_llseek)
+ return;
+
+ pr_info("%s: file '%s' with ops %lx (%pS) might be a stream file\n",
+ current->comm, name, (unsigned long)f->f_op, f->f_op);
+}
+
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
@@ -1097,6 +1112,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
} else {
fsnotify_open(f);
fd_install(fd, f);
+ check_if_stream(f, tmp->name);
}
}
putname(tmp);