31
31
#include <linux/hugetlb.h>
32
32
#include <linux/swapops.h>
33
33
#include <linux/miscdevice.h>
34
+ #include <linux/uio.h>
34
35
35
36
static int sysctl_unprivileged_userfaultfd __read_mostly ;
36
37
@@ -282,7 +283,7 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx,
282
283
/*
283
284
* Verify the pagetables are still not ok after having reigstered into
284
285
* the fault_pending_wqh to avoid userland having to UFFDIO_WAKE any
285
- * userfault that has already been resolved, if userfaultfd_read and
286
+ * userfault that has already been resolved, if userfaultfd_read_iter and
286
287
* UFFDIO_COPY|ZEROPAGE are being run simultaneously on two different
287
288
* threads.
288
289
*/
@@ -1177,34 +1178,34 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
1177
1178
return ret ;
1178
1179
}
1179
1180
1180
- static ssize_t userfaultfd_read (struct file * file , char __user * buf ,
1181
- size_t count , loff_t * ppos )
1181
+ static ssize_t userfaultfd_read_iter (struct kiocb * iocb , struct iov_iter * to )
1182
1182
{
1183
+ struct file * file = iocb -> ki_filp ;
1183
1184
struct userfaultfd_ctx * ctx = file -> private_data ;
1184
1185
ssize_t _ret , ret = 0 ;
1185
1186
struct uffd_msg msg ;
1186
- int no_wait = file -> f_flags & O_NONBLOCK ;
1187
1187
struct inode * inode = file_inode (file );
1188
+ bool no_wait ;
1188
1189
1189
1190
if (!userfaultfd_is_initialized (ctx ))
1190
1191
return - EINVAL ;
1191
1192
1193
+ no_wait = file -> f_flags & O_NONBLOCK || iocb -> ki_flags & IOCB_NOWAIT ;
1192
1194
for (;;) {
1193
- if (count < sizeof (msg ))
1195
+ if (iov_iter_count ( to ) < sizeof (msg ))
1194
1196
return ret ? ret : - EINVAL ;
1195
1197
_ret = userfaultfd_ctx_read (ctx , no_wait , & msg , inode );
1196
1198
if (_ret < 0 )
1197
1199
return ret ? ret : _ret ;
1198
- if (copy_to_user ((__u64 __user * ) buf , & msg , sizeof (msg )))
1200
+ _ret = !copy_to_iter_full (& msg , sizeof (msg ), to );
1201
+ if (_ret )
1199
1202
return ret ? ret : - EFAULT ;
1200
1203
ret += sizeof (msg );
1201
- buf += sizeof (msg );
1202
- count -= sizeof (msg );
1203
1204
/*
1204
1205
* Allow to read more than one fault at time but only
1205
1206
* block if waiting for the very first one.
1206
1207
*/
1207
- no_wait = O_NONBLOCK ;
1208
+ no_wait = true ;
1208
1209
}
1209
1210
}
1210
1211
@@ -2172,7 +2173,7 @@ static const struct file_operations userfaultfd_fops = {
2172
2173
#endif
2173
2174
.release = userfaultfd_release ,
2174
2175
.poll = userfaultfd_poll ,
2175
- .read = userfaultfd_read ,
2176
+ .read_iter = userfaultfd_read_iter ,
2176
2177
.unlocked_ioctl = userfaultfd_ioctl ,
2177
2178
.compat_ioctl = compat_ptr_ioctl ,
2178
2179
.llseek = noop_llseek ,
@@ -2192,6 +2193,7 @@ static void init_once_userfaultfd_ctx(void *mem)
2192
2193
static int new_userfaultfd (int flags )
2193
2194
{
2194
2195
struct userfaultfd_ctx * ctx ;
2196
+ struct file * file ;
2195
2197
int fd ;
2196
2198
2197
2199
BUG_ON (!current -> mm );
@@ -2215,16 +2217,26 @@ static int new_userfaultfd(int flags)
2215
2217
init_rwsem (& ctx -> map_changing_lock );
2216
2218
atomic_set (& ctx -> mmap_changing , 0 );
2217
2219
ctx -> mm = current -> mm ;
2218
- /* prevent the mm struct to be freed */
2219
- mmgrab (ctx -> mm );
2220
+
2221
+ fd = get_unused_fd_flags (flags & UFFD_SHARED_FCNTL_FLAGS );
2222
+ if (fd < 0 )
2223
+ goto err_out ;
2220
2224
2221
2225
/* Create a new inode so that the LSM can block the creation. */
2222
- fd = anon_inode_create_getfd ("[userfaultfd]" , & userfaultfd_fops , ctx ,
2226
+ file = anon_inode_create_getfile ("[userfaultfd]" , & userfaultfd_fops , ctx ,
2223
2227
O_RDONLY | (flags & UFFD_SHARED_FCNTL_FLAGS ), NULL );
2224
- if (fd < 0 ) {
2225
- mmdrop (ctx -> mm );
2226
- kmem_cache_free (userfaultfd_ctx_cachep , ctx );
2228
+ if (IS_ERR (file )) {
2229
+ put_unused_fd (fd );
2230
+ fd = PTR_ERR (file );
2231
+ goto err_out ;
2227
2232
}
2233
+ /* prevent the mm struct to be freed */
2234
+ mmgrab (ctx -> mm );
2235
+ file -> f_mode |= FMODE_NOWAIT ;
2236
+ fd_install (fd , file );
2237
+ return fd ;
2238
+ err_out :
2239
+ kmem_cache_free (userfaultfd_ctx_cachep , ctx );
2228
2240
return fd ;
2229
2241
}
2230
2242
0 commit comments