On Thu, May 07, 2020 at 05:03:17PM -0600, Jens Axboe wrote: > On 5/7/20 4:44 PM, Al Viro wrote: > > On Thu, May 07, 2020 at 04:25:24PM -0600, Jens Axboe wrote: > > > >> static int io_close(struct io_kiocb *req, bool force_nonblock) > >> { > >> + struct files_struct *files = current->files; > >> int ret; > >> > >> req->close.put_file = NULL; > >> - ret = __close_fd_get_file(req->close.fd, &req->close.put_file); > >> + spin_lock(&files->file_lock); > >> + if (req->file->f_op == &io_uring_fops || > >> + req->close.fd == req->ctx->ring_fd) { > >> + spin_unlock(&files->file_lock); > >> + return -EBADF; > >> + } > >> + > >> + ret = __close_fd_get_file_locked(files, req->close.fd, > >> + &req->close.put_file); > > > > Pointless. By that point req->file might have nothing in common with > > anything in any descriptor table. > > How about the below then? Stop using req->file, defer the lookup until > we're in the handler instead. Not sure the 'fd' check makes sense > at this point, but at least we should be consistent in terms of > once we lookup the file and check the f_op. Actually, what _is_ the reason for that check? Note, BTW, that if the file in question happens to be an AF_UNIX socket, closing it will close all references held in SCM_RIGHTS datagrams sitting in its queue, which might very well include io_uring files. IOW, if tries to avoid something really unpleasant, it's not enough. And if it doesn't, then what is it for?