blob: 9e1fd4c20e8962bc1c06c92ba309d3035174eb92 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/read_write.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
7#include <linux/slab.h>
8#include <linux/stat.h>
9#include <linux/fcntl.h>
10#include <linux/file.h>
11#include <linux/uio.h>
Robert Love0eeca282005-07-12 17:06:03 -040012#include <linux/fsnotify.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/security.h>
Paul Gortmaker630d9c42011-11-16 23:57:37 -050014#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/syscalls.h>
Linus Torvaldse28cc712006-01-04 16:20:40 -080016#include <linux/pagemap.h>
Jens Axboed6b29d72007-06-04 09:59:47 +020017#include <linux/splice.h>
Al Viro561c6732013-02-24 10:52:26 -050018#include <linux/compat.h>
Zach Brown29732932015-11-10 16:53:30 -050019#include <linux/mount.h>
Wouter van Kesteren2feb55f2016-02-16 22:20:59 +010020#include <linux/fs.h>
Al Viro06ae43f2013-03-20 13:19:30 -040021#include "internal.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23#include <asm/uaccess.h>
24#include <asm/unistd.h>
25
Al Viroc0bd14af2013-05-04 15:00:54 -040026typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
Al Viro293bc982014-02-11 18:37:41 -050027typedef ssize_t (*iter_fn_t)(struct kiocb *, struct iov_iter *);
Al Viroc0bd14af2013-05-04 15:00:54 -040028
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -080029const struct file_operations generic_ro_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 .llseek = generic_file_llseek,
Al Viroaad4f8b2014-04-02 14:33:16 -040031 .read_iter = generic_file_read_iter,
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 .mmap = generic_file_readonly_mmap,
Jens Axboe534f2aa2007-06-01 14:52:37 +020033 .splice_read = generic_file_splice_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -070034};
35
36EXPORT_SYMBOL(generic_ro_fops);
37
Al Virocccb5a12010-12-17 07:44:05 -050038static inline int unsigned_offsets(struct file *file)
KAMEZAWA Hiroyuki4a3956c2010-10-01 14:20:22 -070039{
Al Virocccb5a12010-12-17 07:44:05 -050040 return file->f_mode & FMODE_UNSIGNED_OFFSET;
KAMEZAWA Hiroyuki4a3956c2010-10-01 14:20:22 -070041}
42
Jie Liu46a1c2c2013-06-25 12:02:13 +080043/**
44 * vfs_setpos - update the file offset for lseek
45 * @file: file structure in question
46 * @offset: file offset to seek to
47 * @maxsize: maximum file size
48 *
49 * This is a low-level filesystem helper for updating the file offset to
50 * the value specified by @offset if the given offset is valid and it is
51 * not equal to the current file offset.
52 *
53 * Return the specified offset on success and -EINVAL on invalid offset.
54 */
55loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
Andi Kleenef3d0fd2011-09-15 16:06:48 -070056{
57 if (offset < 0 && !unsigned_offsets(file))
58 return -EINVAL;
59 if (offset > maxsize)
60 return -EINVAL;
61
62 if (offset != file->f_pos) {
63 file->f_pos = offset;
64 file->f_version = 0;
65 }
66 return offset;
67}
Jie Liu46a1c2c2013-06-25 12:02:13 +080068EXPORT_SYMBOL(vfs_setpos);
Andi Kleenef3d0fd2011-09-15 16:06:48 -070069
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020070/**
Andi Kleen57604952011-09-15 16:06:50 -070071 * generic_file_llseek_size - generic llseek implementation for regular files
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020072 * @file: file structure to seek on
73 * @offset: file offset to seek to
Andrew Morton965c8e52012-12-17 15:59:39 -080074 * @whence: type of seek
Eric Sandeene8b96eb2012-04-30 13:11:29 -050075 * @size: max size of this file in file system
76 * @eof: offset used for SEEK_END position
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020077 *
Andi Kleen57604952011-09-15 16:06:50 -070078 * This is a variant of generic_file_llseek that allows passing in a custom
Eric Sandeene8b96eb2012-04-30 13:11:29 -050079 * maximum file size and a custom EOF position, for e.g. hashed directories
Andi Kleenef3d0fd2011-09-15 16:06:48 -070080 *
81 * Synchronization:
Andi Kleen57604952011-09-15 16:06:50 -070082 * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
Andi Kleenef3d0fd2011-09-15 16:06:48 -070083 * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes.
84 * read/writes behave like SEEK_SET against seeks.
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020085 */
Andi Kleen9465efc2008-06-27 11:05:24 +020086loff_t
Andrew Morton965c8e52012-12-17 15:59:39 -080087generic_file_llseek_size(struct file *file, loff_t offset, int whence,
Eric Sandeene8b96eb2012-04-30 13:11:29 -050088 loff_t maxsize, loff_t eof)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
Andrew Morton965c8e52012-12-17 15:59:39 -080090 switch (whence) {
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020091 case SEEK_END:
Eric Sandeene8b96eb2012-04-30 13:11:29 -050092 offset += eof;
Christoph Hellwig3a8cff42008-08-11 15:37:17 +020093 break;
94 case SEEK_CUR:
Alain Knaff5b6f1eb2008-11-10 17:08:08 -080095 /*
96 * Here we special-case the lseek(fd, 0, SEEK_CUR)
97 * position-querying operation. Avoid rewriting the "same"
98 * f_pos value back to the file because a concurrent read(),
99 * write() or lseek() might have altered it
100 */
101 if (offset == 0)
102 return file->f_pos;
Andi Kleenef3d0fd2011-09-15 16:06:48 -0700103 /*
104 * f_lock protects against read/modify/write race with other
105 * SEEK_CURs. Note that parallel writes and reads behave
106 * like SEEK_SET.
107 */
108 spin_lock(&file->f_lock);
Jie Liu46a1c2c2013-06-25 12:02:13 +0800109 offset = vfs_setpos(file, file->f_pos + offset, maxsize);
Andi Kleenef3d0fd2011-09-15 16:06:48 -0700110 spin_unlock(&file->f_lock);
111 return offset;
Josef Bacik982d8162011-07-18 13:21:35 -0400112 case SEEK_DATA:
113 /*
114 * In the generic case the entire file is data, so as long as
115 * offset isn't at the end of the file then the offset is data.
116 */
Andreas Gruenbacherf3e2e7f2017-09-25 12:23:03 +0200117 if ((unsigned long long)offset >= eof)
Josef Bacik982d8162011-07-18 13:21:35 -0400118 return -ENXIO;
119 break;
120 case SEEK_HOLE:
121 /*
122 * There is a virtual hole at the end of the file, so as long as
123 * offset isn't i_size or larger, return i_size.
124 */
Andreas Gruenbacherf3e2e7f2017-09-25 12:23:03 +0200125 if ((unsigned long long)offset >= eof)
Josef Bacik982d8162011-07-18 13:21:35 -0400126 return -ENXIO;
Eric Sandeene8b96eb2012-04-30 13:11:29 -0500127 offset = eof;
Josef Bacik982d8162011-07-18 13:21:35 -0400128 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 }
Christoph Hellwig3a8cff42008-08-11 15:37:17 +0200130
Jie Liu46a1c2c2013-06-25 12:02:13 +0800131 return vfs_setpos(file, offset, maxsize);
Andi Kleen57604952011-09-15 16:06:50 -0700132}
133EXPORT_SYMBOL(generic_file_llseek_size);
134
135/**
136 * generic_file_llseek - generic llseek implementation for regular files
137 * @file: file structure to seek on
138 * @offset: file offset to seek to
Andrew Morton965c8e52012-12-17 15:59:39 -0800139 * @whence: type of seek
Andi Kleen57604952011-09-15 16:06:50 -0700140 *
141 * This is a generic implemenation of ->llseek useable for all normal local
142 * filesystems. It just updates the file offset to the value specified by
Ming Lei546ae2d2013-04-29 15:06:07 -0700143 * @offset and @whence.
Andi Kleen57604952011-09-15 16:06:50 -0700144 */
Andrew Morton965c8e52012-12-17 15:59:39 -0800145loff_t generic_file_llseek(struct file *file, loff_t offset, int whence)
Andi Kleen57604952011-09-15 16:06:50 -0700146{
147 struct inode *inode = file->f_mapping->host;
148
Andrew Morton965c8e52012-12-17 15:59:39 -0800149 return generic_file_llseek_size(file, offset, whence,
Eric Sandeene8b96eb2012-04-30 13:11:29 -0500150 inode->i_sb->s_maxbytes,
151 i_size_read(inode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
Andi Kleen9465efc2008-06-27 11:05:24 +0200153EXPORT_SYMBOL(generic_file_llseek);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
jan Blunckae6afc32010-05-26 14:44:48 -0700155/**
Al Viro1bf9d142013-06-16 20:27:42 +0400156 * fixed_size_llseek - llseek implementation for fixed-sized devices
157 * @file: file structure to seek on
158 * @offset: file offset to seek to
159 * @whence: type of seek
160 * @size: size of the file
161 *
162 */
163loff_t fixed_size_llseek(struct file *file, loff_t offset, int whence, loff_t size)
164{
165 switch (whence) {
166 case SEEK_SET: case SEEK_CUR: case SEEK_END:
167 return generic_file_llseek_size(file, offset, whence,
168 size, size);
169 default:
170 return -EINVAL;
171 }
172}
173EXPORT_SYMBOL(fixed_size_llseek);
174
175/**
Al Virob25472f2015-12-05 22:04:48 -0500176 * no_seek_end_llseek - llseek implementation for fixed-sized devices
177 * @file: file structure to seek on
178 * @offset: file offset to seek to
179 * @whence: type of seek
180 *
181 */
182loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
183{
184 switch (whence) {
185 case SEEK_SET: case SEEK_CUR:
186 return generic_file_llseek_size(file, offset, whence,
Wouter van Kesteren2feb55f2016-02-16 22:20:59 +0100187 OFFSET_MAX, 0);
Al Virob25472f2015-12-05 22:04:48 -0500188 default:
189 return -EINVAL;
190 }
191}
192EXPORT_SYMBOL(no_seek_end_llseek);
193
194/**
195 * no_seek_end_llseek_size - llseek implementation for fixed-sized devices
196 * @file: file structure to seek on
197 * @offset: file offset to seek to
198 * @whence: type of seek
199 * @size: maximal offset allowed
200 *
201 */
202loff_t no_seek_end_llseek_size(struct file *file, loff_t offset, int whence, loff_t size)
203{
204 switch (whence) {
205 case SEEK_SET: case SEEK_CUR:
206 return generic_file_llseek_size(file, offset, whence,
207 size, 0);
208 default:
209 return -EINVAL;
210 }
211}
212EXPORT_SYMBOL(no_seek_end_llseek_size);
213
214/**
jan Blunckae6afc32010-05-26 14:44:48 -0700215 * noop_llseek - No Operation Performed llseek implementation
216 * @file: file structure to seek on
217 * @offset: file offset to seek to
Andrew Morton965c8e52012-12-17 15:59:39 -0800218 * @whence: type of seek
jan Blunckae6afc32010-05-26 14:44:48 -0700219 *
220 * This is an implementation of ->llseek useable for the rare special case when
221 * userspace expects the seek to succeed but the (device) file is actually not
222 * able to perform the seek. In this case you use noop_llseek() instead of
223 * falling back to the default implementation of ->llseek.
224 */
Andrew Morton965c8e52012-12-17 15:59:39 -0800225loff_t noop_llseek(struct file *file, loff_t offset, int whence)
jan Blunckae6afc32010-05-26 14:44:48 -0700226{
227 return file->f_pos;
228}
229EXPORT_SYMBOL(noop_llseek);
230
Andrew Morton965c8e52012-12-17 15:59:39 -0800231loff_t no_llseek(struct file *file, loff_t offset, int whence)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
233 return -ESPIPE;
234}
235EXPORT_SYMBOL(no_llseek);
236
Andrew Morton965c8e52012-12-17 15:59:39 -0800237loff_t default_llseek(struct file *file, loff_t offset, int whence)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
Al Viro496ad9a2013-01-23 17:07:38 -0500239 struct inode *inode = file_inode(file);
David Sterba16abef02008-04-22 15:09:22 +0200240 loff_t retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
Al Viro59551022016-01-22 15:40:57 -0500242 inode_lock(inode);
Andrew Morton965c8e52012-12-17 15:59:39 -0800243 switch (whence) {
Chris Snook7b8e8922007-05-08 00:24:13 -0700244 case SEEK_END:
Josef Bacik982d8162011-07-18 13:21:35 -0400245 offset += i_size_read(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 break;
Chris Snook7b8e8922007-05-08 00:24:13 -0700247 case SEEK_CUR:
Alain Knaff5b6f1eb2008-11-10 17:08:08 -0800248 if (offset == 0) {
249 retval = file->f_pos;
250 goto out;
251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 offset += file->f_pos;
Josef Bacik982d8162011-07-18 13:21:35 -0400253 break;
254 case SEEK_DATA:
255 /*
256 * In the generic case the entire file is data, so as
257 * long as offset isn't at the end of the file then the
258 * offset is data.
259 */
Dan Carpenterbacb2d82011-07-26 17:25:20 +0300260 if (offset >= inode->i_size) {
261 retval = -ENXIO;
262 goto out;
263 }
Josef Bacik982d8162011-07-18 13:21:35 -0400264 break;
265 case SEEK_HOLE:
266 /*
267 * There is a virtual hole at the end of the file, so
268 * as long as offset isn't i_size or larger, return
269 * i_size.
270 */
Dan Carpenterbacb2d82011-07-26 17:25:20 +0300271 if (offset >= inode->i_size) {
272 retval = -ENXIO;
273 goto out;
274 }
Josef Bacik982d8162011-07-18 13:21:35 -0400275 offset = inode->i_size;
276 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 }
278 retval = -EINVAL;
Al Virocccb5a12010-12-17 07:44:05 -0500279 if (offset >= 0 || unsigned_offsets(file)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (offset != file->f_pos) {
281 file->f_pos = offset;
282 file->f_version = 0;
283 }
284 retval = offset;
285 }
Alain Knaff5b6f1eb2008-11-10 17:08:08 -0800286out:
Al Viro59551022016-01-22 15:40:57 -0500287 inode_unlock(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 return retval;
289}
290EXPORT_SYMBOL(default_llseek);
291
Andrew Morton965c8e52012-12-17 15:59:39 -0800292loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
294 loff_t (*fn)(struct file *, loff_t, int);
295
296 fn = no_llseek;
297 if (file->f_mode & FMODE_LSEEK) {
Al Viro72c2d532013-09-22 16:27:52 -0400298 if (file->f_op->llseek)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 fn = file->f_op->llseek;
300 }
Andrew Morton965c8e52012-12-17 15:59:39 -0800301 return fn(file, offset, whence);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302}
303EXPORT_SYMBOL(vfs_llseek);
304
Andrew Morton965c8e52012-12-17 15:59:39 -0800305SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
307 off_t retval;
Linus Torvalds9c225f22014-03-03 09:36:58 -0800308 struct fd f = fdget_pos(fd);
Al Viro2903ff02012-08-28 12:52:22 -0400309 if (!f.file)
310 return -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 retval = -EINVAL;
Andrew Morton965c8e52012-12-17 15:59:39 -0800313 if (whence <= SEEK_MAX) {
314 loff_t res = vfs_llseek(f.file, offset, whence);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 retval = res;
316 if (res != (loff_t)retval)
317 retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
318 }
Linus Torvalds9c225f22014-03-03 09:36:58 -0800319 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 return retval;
321}
322
Al Viro561c6732013-02-24 10:52:26 -0500323#ifdef CONFIG_COMPAT
324COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence)
325{
326 return sys_lseek(fd, offset, whence);
327}
328#endif
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330#ifdef __ARCH_WANT_SYS_LLSEEK
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100331SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
332 unsigned long, offset_low, loff_t __user *, result,
Andrew Morton965c8e52012-12-17 15:59:39 -0800333 unsigned int, whence)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
335 int retval;
Eric Biggersd7a15f82014-03-16 14:24:08 -0500336 struct fd f = fdget_pos(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 loff_t offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Al Viro2903ff02012-08-28 12:52:22 -0400339 if (!f.file)
340 return -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
342 retval = -EINVAL;
Andrew Morton965c8e52012-12-17 15:59:39 -0800343 if (whence > SEEK_MAX)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 goto out_putf;
345
Al Viro2903ff02012-08-28 12:52:22 -0400346 offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low,
Andrew Morton965c8e52012-12-17 15:59:39 -0800347 whence);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 retval = (int)offset;
350 if (offset >= 0) {
351 retval = -EFAULT;
352 if (!copy_to_user(result, &offset, sizeof(offset)))
353 retval = 0;
354 }
355out_putf:
Eric Biggersd7a15f82014-03-16 14:24:08 -0500356 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return retval;
358}
359#endif
360
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100361ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos)
362{
363 struct kiocb kiocb;
364 ssize_t ret;
365
366 if (!file->f_op->read_iter)
367 return -EINVAL;
368
369 init_sync_kiocb(&kiocb, file);
370 kiocb.ki_pos = *ppos;
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100371
372 iter->type |= READ;
373 ret = file->f_op->read_iter(&kiocb, iter);
Christoph Hellwig599bd192015-02-11 19:59:44 +0100374 BUG_ON(ret == -EIOCBQUEUED);
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100375 if (ret > 0)
376 *ppos = kiocb.ki_pos;
377 return ret;
378}
379EXPORT_SYMBOL(vfs_iter_read);
380
381ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
382{
383 struct kiocb kiocb;
384 ssize_t ret;
385
386 if (!file->f_op->write_iter)
387 return -EINVAL;
388
389 init_sync_kiocb(&kiocb, file);
390 kiocb.ki_pos = *ppos;
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100391
392 iter->type |= WRITE;
393 ret = file->f_op->write_iter(&kiocb, iter);
Christoph Hellwig599bd192015-02-11 19:59:44 +0100394 BUG_ON(ret == -EIOCBQUEUED);
Jimmy Durand Wesolowskic5cc9332019-01-31 15:19:39 +0100395 if (ret > 0) {
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100396 *ppos = kiocb.ki_pos;
Jimmy Durand Wesolowskic5cc9332019-01-31 15:19:39 +0100397 fsnotify_modify(file);
398 }
Christoph Hellwigdbe4e192015-01-25 21:11:59 +0100399 return ret;
400}
401EXPORT_SYMBOL(vfs_iter_write);
402
Al Viro68d70d02013-06-19 15:26:04 +0400403int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
405 struct inode *inode;
406 loff_t pos;
James Morrisc43e2592008-01-12 22:05:48 +1100407 int retval = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Al Viro496ad9a2013-01-23 17:07:38 -0500409 inode = file_inode(file);
Linus Torvaldse28cc712006-01-04 16:20:40 -0800410 if (unlikely((ssize_t) count < 0))
James Morrisc43e2592008-01-12 22:05:48 +1100411 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 pos = *ppos;
Al Virocccb5a12010-12-17 07:44:05 -0500413 if (unlikely(pos < 0)) {
414 if (!unsigned_offsets(file))
415 return retval;
416 if (count >= -pos) /* both values are in 0..LLONG_MAX */
417 return -EOVERFLOW;
418 } else if (unlikely((loff_t) (pos + count) < 0)) {
419 if (!unsigned_offsets(file))
KAMEZAWA Hiroyuki4a3956c2010-10-01 14:20:22 -0700420 return retval;
421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Jeff Laytonbd61e0a2015-01-16 15:05:55 -0500423 if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
Christoph Hellwigacc15572015-12-03 12:59:49 +0100424 retval = locks_mandatory_area(inode, file, pos, pos + count - 1,
425 read_write == READ ? F_RDLCK : F_WRLCK);
Linus Torvaldse28cc712006-01-04 16:20:40 -0800426 if (retval < 0)
427 return retval;
428 }
Al Virobc613842016-03-31 21:48:20 -0400429 return security_file_permission(file,
James Morrisc43e2592008-01-12 22:05:48 +1100430 read_write == READ ? MAY_READ : MAY_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431}
432
Al Viro5d5d5682015-04-03 15:41:18 -0400433static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
Al Viro293bc982014-02-11 18:37:41 -0500434{
435 struct iovec iov = { .iov_base = buf, .iov_len = len };
436 struct kiocb kiocb;
437 struct iov_iter iter;
438 ssize_t ret;
439
440 init_sync_kiocb(&kiocb, filp);
441 kiocb.ki_pos = *ppos;
Al Viro293bc982014-02-11 18:37:41 -0500442 iov_iter_init(&iter, READ, &iov, 1, len);
443
444 ret = filp->f_op->read_iter(&kiocb, &iter);
Christoph Hellwig599bd192015-02-11 19:59:44 +0100445 BUG_ON(ret == -EIOCBQUEUED);
Al Viro293bc982014-02-11 18:37:41 -0500446 *ppos = kiocb.ki_pos;
447 return ret;
448}
449
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200450ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
451 loff_t *pos)
452{
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200453 if (file->f_op->read)
Al Viro3d04c8a2015-04-03 15:09:18 -0400454 return file->f_op->read(file, buf, count, pos);
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200455 else if (file->f_op->read_iter)
Al Viro3d04c8a2015-04-03 15:09:18 -0400456 return new_sync_read(file, buf, count, pos);
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200457 else
Al Viro3d04c8a2015-04-03 15:09:18 -0400458 return -EINVAL;
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200459}
Al Viro3d04c8a2015-04-03 15:09:18 -0400460EXPORT_SYMBOL(__vfs_read);
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
463{
464 ssize_t ret;
465
466 if (!(file->f_mode & FMODE_READ))
467 return -EBADF;
Al Viro7f7f25e2014-02-11 17:49:24 -0500468 if (!(file->f_mode & FMODE_CAN_READ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return -EINVAL;
470 if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
471 return -EFAULT;
472
473 ret = rw_verify_area(READ, file, pos, count);
Al Virobc613842016-03-31 21:48:20 -0400474 if (!ret) {
475 if (count > MAX_RW_COUNT)
476 count = MAX_RW_COUNT;
Dmitry Kasatkin6fb50322014-11-05 17:01:17 +0200477 ret = __vfs_read(file, buf, count, pos);
James Morrisc43e2592008-01-12 22:05:48 +1100478 if (ret > 0) {
Eric Paris2a12a9d2009-12-17 21:24:21 -0500479 fsnotify_access(file);
James Morrisc43e2592008-01-12 22:05:48 +1100480 add_rchar(current, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 }
James Morrisc43e2592008-01-12 22:05:48 +1100482 inc_syscr(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484
485 return ret;
486}
487
488EXPORT_SYMBOL(vfs_read);
489
Al Viro5d5d5682015-04-03 15:41:18 -0400490static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
Al Viro293bc982014-02-11 18:37:41 -0500491{
492 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
493 struct kiocb kiocb;
494 struct iov_iter iter;
495 ssize_t ret;
496
497 init_sync_kiocb(&kiocb, filp);
498 kiocb.ki_pos = *ppos;
Al Viro293bc982014-02-11 18:37:41 -0500499 iov_iter_init(&iter, WRITE, &iov, 1, len);
500
501 ret = filp->f_op->write_iter(&kiocb, &iter);
Christoph Hellwig599bd192015-02-11 19:59:44 +0100502 BUG_ON(ret == -EIOCBQUEUED);
Al Virof765b132015-04-06 20:50:38 -0400503 if (ret > 0)
504 *ppos = kiocb.ki_pos;
Al Viro293bc982014-02-11 18:37:41 -0500505 return ret;
506}
507
Al Viro493c84c2015-04-03 15:06:43 -0400508ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
509 loff_t *pos)
510{
511 if (file->f_op->write)
512 return file->f_op->write(file, p, count, pos);
Al Viro493c84c2015-04-03 15:06:43 -0400513 else if (file->f_op->write_iter)
514 return new_sync_write(file, p, count, pos);
515 else
516 return -EINVAL;
517}
518EXPORT_SYMBOL(__vfs_write);
519
Al Viro06ae43f2013-03-20 13:19:30 -0400520ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
521{
522 mm_segment_t old_fs;
523 const char __user *p;
524 ssize_t ret;
525
Al Viro7f7f25e2014-02-11 17:49:24 -0500526 if (!(file->f_mode & FMODE_CAN_WRITE))
Al Viro3e84f482013-03-27 15:20:30 +0000527 return -EINVAL;
528
Al Viro06ae43f2013-03-20 13:19:30 -0400529 old_fs = get_fs();
530 set_fs(get_ds());
531 p = (__force const char __user *)buf;
532 if (count > MAX_RW_COUNT)
533 count = MAX_RW_COUNT;
Al Viro493c84c2015-04-03 15:06:43 -0400534 ret = __vfs_write(file, p, count, pos);
Al Viro06ae43f2013-03-20 13:19:30 -0400535 set_fs(old_fs);
536 if (ret > 0) {
537 fsnotify_modify(file);
538 add_wchar(current, ret);
539 }
540 inc_syscw(current);
541 return ret;
542}
543
Al Viro2ec3a122014-08-19 11:48:09 -0400544EXPORT_SYMBOL(__kernel_write);
545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
547{
548 ssize_t ret;
549
550 if (!(file->f_mode & FMODE_WRITE))
551 return -EBADF;
Al Viro7f7f25e2014-02-11 17:49:24 -0500552 if (!(file->f_mode & FMODE_CAN_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 return -EINVAL;
554 if (unlikely(!access_ok(VERIFY_READ, buf, count)))
555 return -EFAULT;
556
557 ret = rw_verify_area(WRITE, file, pos, count);
Al Virobc613842016-03-31 21:48:20 -0400558 if (!ret) {
559 if (count > MAX_RW_COUNT)
560 count = MAX_RW_COUNT;
Al Viro03d95eb2013-03-20 13:04:20 -0400561 file_start_write(file);
Al Viro493c84c2015-04-03 15:06:43 -0400562 ret = __vfs_write(file, buf, count, pos);
James Morrisc43e2592008-01-12 22:05:48 +1100563 if (ret > 0) {
Eric Paris2a12a9d2009-12-17 21:24:21 -0500564 fsnotify_modify(file);
James Morrisc43e2592008-01-12 22:05:48 +1100565 add_wchar(current, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 }
James Morrisc43e2592008-01-12 22:05:48 +1100567 inc_syscw(current);
Al Viro03d95eb2013-03-20 13:04:20 -0400568 file_end_write(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
570
571 return ret;
572}
573
574EXPORT_SYMBOL(vfs_write);
575
576static inline loff_t file_pos_read(struct file *file)
577{
Kirill Smelkov9c829b62019-03-26 22:20:43 +0000578 return file->f_mode & FMODE_STREAM ? 0 : file->f_pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579}
580
581static inline void file_pos_write(struct file *file, loff_t pos)
582{
Kirill Smelkov9c829b62019-03-26 22:20:43 +0000583 if ((file->f_mode & FMODE_STREAM) == 0)
584 file->f_pos = pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586
Heiko Carstens3cdad422009-01-14 14:14:22 +0100587SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588{
Linus Torvalds9c225f22014-03-03 09:36:58 -0800589 struct fd f = fdget_pos(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Al Viro2903ff02012-08-28 12:52:22 -0400592 if (f.file) {
593 loff_t pos = file_pos_read(f.file);
594 ret = vfs_read(f.file, buf, count, &pos);
Al Viro5faf1532013-06-15 05:49:36 +0400595 if (ret >= 0)
596 file_pos_write(f.file, pos);
Linus Torvalds9c225f22014-03-03 09:36:58 -0800597 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 return ret;
600}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Heiko Carstens3cdad422009-01-14 14:14:22 +0100602SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
603 size_t, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
Linus Torvalds9c225f22014-03-03 09:36:58 -0800605 struct fd f = fdget_pos(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Al Viro2903ff02012-08-28 12:52:22 -0400608 if (f.file) {
609 loff_t pos = file_pos_read(f.file);
610 ret = vfs_write(f.file, buf, count, &pos);
Al Viro5faf1532013-06-15 05:49:36 +0400611 if (ret >= 0)
612 file_pos_write(f.file, pos);
Linus Torvalds9c225f22014-03-03 09:36:58 -0800613 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
615
616 return ret;
617}
618
Al Viro4a0fd5b2013-01-21 15:16:58 -0500619SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
620 size_t, count, loff_t, pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
Al Viro2903ff02012-08-28 12:52:22 -0400622 struct fd f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
625 if (pos < 0)
626 return -EINVAL;
627
Al Viro2903ff02012-08-28 12:52:22 -0400628 f = fdget(fd);
629 if (f.file) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 ret = -ESPIPE;
Al Viro2903ff02012-08-28 12:52:22 -0400631 if (f.file->f_mode & FMODE_PREAD)
632 ret = vfs_read(f.file, buf, count, &pos);
633 fdput(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 }
635
636 return ret;
637}
638
Al Viro4a0fd5b2013-01-21 15:16:58 -0500639SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
640 size_t, count, loff_t, pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
Al Viro2903ff02012-08-28 12:52:22 -0400642 struct fd f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 if (pos < 0)
646 return -EINVAL;
647
Al Viro2903ff02012-08-28 12:52:22 -0400648 f = fdget(fd);
649 if (f.file) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 ret = -ESPIPE;
Al Viro2903ff02012-08-28 12:52:22 -0400651 if (f.file->f_mode & FMODE_PWRITE)
652 ret = vfs_write(f.file, buf, count, &pos);
653 fdput(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
656 return ret;
657}
658
659/*
660 * Reduce an iovec's length in-place. Return the resulting number of segments
661 */
662unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
663{
664 unsigned long seg = 0;
665 size_t len = 0;
666
667 while (seg < nr_segs) {
668 seg++;
669 if (len + iov->iov_len >= to) {
670 iov->iov_len = to - len;
671 break;
672 }
673 len += iov->iov_len;
674 iov++;
675 }
676 return seg;
677}
Eric Sandeen19295522008-01-28 23:58:27 -0500678EXPORT_SYMBOL(iov_shorten);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Al Viroac15ac02015-03-20 20:10:21 -0400680static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100681 loff_t *ppos, iter_fn_t fn, int flags)
Al Viro293bc982014-02-11 18:37:41 -0500682{
683 struct kiocb kiocb;
Al Viro293bc982014-02-11 18:37:41 -0500684 ssize_t ret;
685
Christoph Hellwige864f392016-04-07 08:52:03 -0700686 if (flags & ~(RWF_HIPRI | RWF_DSYNC | RWF_SYNC))
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100687 return -EOPNOTSUPP;
688
Al Viro293bc982014-02-11 18:37:41 -0500689 init_sync_kiocb(&kiocb, filp);
Christoph Hellwig97be7eb2016-03-03 16:04:01 +0100690 if (flags & RWF_HIPRI)
691 kiocb.ki_flags |= IOCB_HIPRI;
Christoph Hellwige864f392016-04-07 08:52:03 -0700692 if (flags & RWF_DSYNC)
693 kiocb.ki_flags |= IOCB_DSYNC;
694 if (flags & RWF_SYNC)
695 kiocb.ki_flags |= (IOCB_DSYNC | IOCB_SYNC);
Al Viro293bc982014-02-11 18:37:41 -0500696 kiocb.ki_pos = *ppos;
Al Viro293bc982014-02-11 18:37:41 -0500697
Al Viroac15ac02015-03-20 20:10:21 -0400698 ret = fn(&kiocb, iter);
Christoph Hellwig599bd192015-02-11 19:59:44 +0100699 BUG_ON(ret == -EIOCBQUEUED);
Al Viro293bc982014-02-11 18:37:41 -0500700 *ppos = kiocb.ki_pos;
701 return ret;
702}
703
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700704/* Do it by hand, with file-ops */
Al Viroac15ac02015-03-20 20:10:21 -0400705static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100706 loff_t *ppos, io_fn_t fn, int flags)
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700707{
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700708 ssize_t ret = 0;
709
Christoph Hellwig97be7eb2016-03-03 16:04:01 +0100710 if (flags & ~RWF_HIPRI)
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100711 return -EOPNOTSUPP;
712
Al Viroac15ac02015-03-20 20:10:21 -0400713 while (iov_iter_count(iter)) {
714 struct iovec iovec = iov_iter_iovec(iter);
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700715 ssize_t nr;
716
Al Viroac15ac02015-03-20 20:10:21 -0400717 nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos);
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700718
719 if (nr < 0) {
720 if (!ret)
721 ret = nr;
722 break;
723 }
724 ret += nr;
Al Viroac15ac02015-03-20 20:10:21 -0400725 if (nr != iovec.iov_len)
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700726 break;
Al Viroac15ac02015-03-20 20:10:21 -0400727 iov_iter_advance(iter, nr);
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700728 }
729
730 return ret;
731}
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733/* A write operation does a read from user space and vice versa */
734#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
735
Vegard Nossumffecee42016-10-08 11:18:07 +0200736/**
737 * rw_copy_check_uvector() - Copy an array of &struct iovec from userspace
738 * into the kernel and check that it is valid.
739 *
740 * @type: One of %CHECK_IOVEC_ONLY, %READ, or %WRITE.
741 * @uvector: Pointer to the userspace array.
742 * @nr_segs: Number of elements in userspace array.
743 * @fast_segs: Number of elements in @fast_pointer.
744 * @fast_pointer: Pointer to (usually small on-stack) kernel array.
745 * @ret_pointer: (output parameter) Pointer to a variable that will point to
746 * either @fast_pointer, a newly allocated kernel array, or NULL,
747 * depending on which array was used.
748 *
749 * This function copies an array of &struct iovec of @nr_segs from
750 * userspace into the kernel and checks that each element is valid (e.g.
751 * it does not point to a kernel address or cause overflow by being too
752 * large, etc.).
753 *
754 * As an optimization, the caller may provide a pointer to a small
755 * on-stack array in @fast_pointer, typically %UIO_FASTIOV elements long
756 * (the size of this array, or 0 if unused, should be given in @fast_segs).
757 *
758 * @ret_pointer will always point to the array that was used, so the
759 * caller must take care not to call kfree() on it e.g. in case the
760 * @fast_pointer array was used and it was allocated on the stack.
761 *
762 * Return: The total number of bytes covered by the iovec array on success
763 * or a negative error code on error.
764 */
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700765ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
766 unsigned long nr_segs, unsigned long fast_segs,
767 struct iovec *fast_pointer,
Christopher Yeohac34ebb2012-05-31 16:26:42 -0700768 struct iovec **ret_pointer)
Linus Torvalds435f49a2010-10-29 10:36:49 -0700769{
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700770 unsigned long seg;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700771 ssize_t ret;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700772 struct iovec *iov = fast_pointer;
773
Linus Torvalds435f49a2010-10-29 10:36:49 -0700774 /*
775 * SuS says "The readv() function *may* fail if the iovcnt argument
776 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
777 * traditionally returned zero for zero segments, so...
778 */
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700779 if (nr_segs == 0) {
780 ret = 0;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700781 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700782 }
783
Linus Torvalds435f49a2010-10-29 10:36:49 -0700784 /*
785 * First get the "struct iovec" from user memory and
786 * verify all the pointers
787 */
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700788 if (nr_segs > UIO_MAXIOV) {
789 ret = -EINVAL;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700790 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700791 }
792 if (nr_segs > fast_segs) {
Linus Torvalds435f49a2010-10-29 10:36:49 -0700793 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700794 if (iov == NULL) {
795 ret = -ENOMEM;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700796 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700797 }
Linus Torvalds435f49a2010-10-29 10:36:49 -0700798 }
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700799 if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
800 ret = -EFAULT;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700801 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700802 }
803
Linus Torvalds435f49a2010-10-29 10:36:49 -0700804 /*
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700805 * According to the Single Unix Specification we should return EINVAL
806 * if an element length is < 0 when cast to ssize_t or if the
807 * total length would overflow the ssize_t return value of the
808 * system call.
Linus Torvalds435f49a2010-10-29 10:36:49 -0700809 *
810 * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the
811 * overflow case.
812 */
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700813 ret = 0;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700814 for (seg = 0; seg < nr_segs; seg++) {
815 void __user *buf = iov[seg].iov_base;
816 ssize_t len = (ssize_t)iov[seg].iov_len;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700817
818 /* see if we we're about to use an invalid len or if
819 * it's about to overflow ssize_t */
Linus Torvalds435f49a2010-10-29 10:36:49 -0700820 if (len < 0) {
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700821 ret = -EINVAL;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700822 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700823 }
Christopher Yeohac34ebb2012-05-31 16:26:42 -0700824 if (type >= 0
Christopher Yeohfcf63402011-10-31 17:06:39 -0700825 && unlikely(!access_ok(vrfy_dir(type), buf, len))) {
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700826 ret = -EFAULT;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700827 goto out;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700828 }
Linus Torvalds435f49a2010-10-29 10:36:49 -0700829 if (len > MAX_RW_COUNT - ret) {
830 len = MAX_RW_COUNT - ret;
831 iov[seg].iov_len = len;
832 }
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700833 ret += len;
Linus Torvalds435f49a2010-10-29 10:36:49 -0700834 }
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700835out:
836 *ret_pointer = iov;
837 return ret;
838}
839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840static ssize_t do_readv_writev(int type, struct file *file,
841 const struct iovec __user * uvector,
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100842 unsigned long nr_segs, loff_t *pos,
843 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 size_t tot_len;
846 struct iovec iovstack[UIO_FASTIOV];
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700847 struct iovec *iov = iovstack;
Al Viroac15ac02015-03-20 20:10:21 -0400848 struct iov_iter iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 ssize_t ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 io_fn_t fn;
Al Viro293bc982014-02-11 18:37:41 -0500851 iter_fn_t iter_fn;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Al Viro0504c072015-03-21 19:40:11 -0400853 ret = import_iovec(type, uvector, nr_segs,
854 ARRAY_SIZE(iovstack), &iov, &iter);
855 if (ret < 0)
856 return ret;
Badari Pulavartyeed4e512006-09-30 23:28:49 -0700857
Al Viro0504c072015-03-21 19:40:11 -0400858 tot_len = iov_iter_count(&iter);
859 if (!tot_len)
860 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 ret = rw_verify_area(type, file, pos, tot_len);
Linus Torvaldse28cc712006-01-04 16:20:40 -0800862 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 goto out;
864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 if (type == READ) {
866 fn = file->f_op->read;
Al Viro293bc982014-02-11 18:37:41 -0500867 iter_fn = file->f_op->read_iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 } else {
869 fn = (io_fn_t)file->f_op->write;
Al Viro293bc982014-02-11 18:37:41 -0500870 iter_fn = file->f_op->write_iter;
Al Viro03d95eb2013-03-20 13:04:20 -0400871 file_start_write(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873
Al Viro293bc982014-02-11 18:37:41 -0500874 if (iter_fn)
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100875 ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags);
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700876 else
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100877 ret = do_loop_readv_writev(file, &iter, pos, fn, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Al Viro03d95eb2013-03-20 13:04:20 -0400879 if (type != READ)
880 file_end_write(file);
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882out:
Al Viro0504c072015-03-21 19:40:11 -0400883 kfree(iov);
Robert Love0eeca282005-07-12 17:06:03 -0400884 if ((ret + (type == READ)) > 0) {
885 if (type == READ)
Eric Paris2a12a9d2009-12-17 21:24:21 -0500886 fsnotify_access(file);
Robert Love0eeca282005-07-12 17:06:03 -0400887 else
Eric Paris2a12a9d2009-12-17 21:24:21 -0500888 fsnotify_modify(file);
Robert Love0eeca282005-07-12 17:06:03 -0400889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891}
892
893ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100894 unsigned long vlen, loff_t *pos, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 if (!(file->f_mode & FMODE_READ))
897 return -EBADF;
Al Viro7f7f25e2014-02-11 17:49:24 -0500898 if (!(file->f_mode & FMODE_CAN_READ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 return -EINVAL;
900
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100901 return do_readv_writev(READ, file, vec, vlen, pos, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902}
903
904EXPORT_SYMBOL(vfs_readv);
905
906ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100907 unsigned long vlen, loff_t *pos, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
909 if (!(file->f_mode & FMODE_WRITE))
910 return -EBADF;
Al Viro7f7f25e2014-02-11 17:49:24 -0500911 if (!(file->f_mode & FMODE_CAN_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 return -EINVAL;
913
Christoph Hellwig793b80e2016-03-03 16:03:58 +0100914 return do_readv_writev(WRITE, file, vec, vlen, pos, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915}
916
917EXPORT_SYMBOL(vfs_writev);
918
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100919static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
920 unsigned long vlen, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
Linus Torvalds9c225f22014-03-03 09:36:58 -0800922 struct fd f = fdget_pos(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Al Viro2903ff02012-08-28 12:52:22 -0400925 if (f.file) {
926 loff_t pos = file_pos_read(f.file);
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100927 ret = vfs_readv(f.file, vec, vlen, &pos, flags);
Al Viro5faf1532013-06-15 05:49:36 +0400928 if (ret >= 0)
929 file_pos_write(f.file, pos);
Linus Torvalds9c225f22014-03-03 09:36:58 -0800930 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
932
933 if (ret > 0)
Alexey Dobriyan4b98d112007-02-10 01:46:45 -0800934 add_rchar(current, ret);
935 inc_syscr(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 return ret;
937}
938
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100939static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
940 unsigned long vlen, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
Linus Torvalds9c225f22014-03-03 09:36:58 -0800942 struct fd f = fdget_pos(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 ssize_t ret = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Al Viro2903ff02012-08-28 12:52:22 -0400945 if (f.file) {
946 loff_t pos = file_pos_read(f.file);
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100947 ret = vfs_writev(f.file, vec, vlen, &pos, flags);
Al Viro5faf1532013-06-15 05:49:36 +0400948 if (ret >= 0)
949 file_pos_write(f.file, pos);
Linus Torvalds9c225f22014-03-03 09:36:58 -0800950 fdput_pos(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 }
952
953 if (ret > 0)
Alexey Dobriyan4b98d112007-02-10 01:46:45 -0800954 add_wchar(current, ret);
955 inc_syscw(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 return ret;
957}
958
Linus Torvalds601cc112009-04-03 08:03:22 -0700959static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700960{
Linus Torvalds601cc112009-04-03 08:03:22 -0700961#define HALF_LONG_BITS (BITS_PER_LONG / 2)
962 return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
963}
964
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100965static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
966 unsigned long vlen, loff_t pos, int flags)
Linus Torvalds601cc112009-04-03 08:03:22 -0700967{
Al Viro2903ff02012-08-28 12:52:22 -0400968 struct fd f;
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700969 ssize_t ret = -EBADF;
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700970
971 if (pos < 0)
972 return -EINVAL;
973
Al Viro2903ff02012-08-28 12:52:22 -0400974 f = fdget(fd);
975 if (f.file) {
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700976 ret = -ESPIPE;
Al Viro2903ff02012-08-28 12:52:22 -0400977 if (f.file->f_mode & FMODE_PREAD)
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100978 ret = vfs_readv(f.file, vec, vlen, &pos, flags);
Al Viro2903ff02012-08-28 12:52:22 -0400979 fdput(f);
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700980 }
981
982 if (ret > 0)
983 add_rchar(current, ret);
984 inc_syscr(current);
985 return ret;
986}
987
Milosz Tanskif17d8b32016-03-03 16:03:59 +0100988static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
989 unsigned long vlen, loff_t pos, int flags)
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700990{
Al Viro2903ff02012-08-28 12:52:22 -0400991 struct fd f;
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700992 ssize_t ret = -EBADF;
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700993
994 if (pos < 0)
995 return -EINVAL;
996
Al Viro2903ff02012-08-28 12:52:22 -0400997 f = fdget(fd);
998 if (f.file) {
Gerd Hoffmannf3554f42009-04-02 16:59:23 -0700999 ret = -ESPIPE;
Al Viro2903ff02012-08-28 12:52:22 -04001000 if (f.file->f_mode & FMODE_PWRITE)
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001001 ret = vfs_writev(f.file, vec, vlen, &pos, flags);
Al Viro2903ff02012-08-28 12:52:22 -04001002 fdput(f);
Gerd Hoffmannf3554f42009-04-02 16:59:23 -07001003 }
1004
1005 if (ret > 0)
1006 add_wchar(current, ret);
1007 inc_syscw(current);
1008 return ret;
1009}
1010
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001011SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
1012 unsigned long, vlen)
1013{
1014 return do_readv(fd, vec, vlen, 0);
1015}
1016
1017SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
1018 unsigned long, vlen)
1019{
1020 return do_writev(fd, vec, vlen, 0);
1021}
1022
1023SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
1024 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1025{
1026 loff_t pos = pos_from_hilo(pos_h, pos_l);
1027
1028 return do_preadv(fd, vec, vlen, pos, 0);
1029}
1030
1031SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec,
1032 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1033 int, flags)
1034{
1035 loff_t pos = pos_from_hilo(pos_h, pos_l);
1036
1037 if (pos == -1)
1038 return do_readv(fd, vec, vlen, flags);
1039
1040 return do_preadv(fd, vec, vlen, pos, flags);
1041}
1042
1043SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
1044 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
1045{
1046 loff_t pos = pos_from_hilo(pos_h, pos_l);
1047
1048 return do_pwritev(fd, vec, vlen, pos, 0);
1049}
1050
1051SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec,
1052 unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
1053 int, flags)
1054{
1055 loff_t pos = pos_from_hilo(pos_h, pos_l);
1056
1057 if (pos == -1)
1058 return do_writev(fd, vec, vlen, flags);
1059
1060 return do_pwritev(fd, vec, vlen, pos, flags);
1061}
1062
Al Viro72ec3512013-03-20 10:42:10 -04001063#ifdef CONFIG_COMPAT
1064
1065static ssize_t compat_do_readv_writev(int type, struct file *file,
1066 const struct compat_iovec __user *uvector,
Christoph Hellwig793b80e2016-03-03 16:03:58 +01001067 unsigned long nr_segs, loff_t *pos,
1068 int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001069{
1070 compat_ssize_t tot_len;
1071 struct iovec iovstack[UIO_FASTIOV];
1072 struct iovec *iov = iovstack;
Al Viroac15ac02015-03-20 20:10:21 -04001073 struct iov_iter iter;
Al Viro72ec3512013-03-20 10:42:10 -04001074 ssize_t ret;
1075 io_fn_t fn;
Al Viro293bc982014-02-11 18:37:41 -05001076 iter_fn_t iter_fn;
Al Viro72ec3512013-03-20 10:42:10 -04001077
Al Viro0504c072015-03-21 19:40:11 -04001078 ret = compat_import_iovec(type, uvector, nr_segs,
1079 UIO_FASTIOV, &iov, &iter);
1080 if (ret < 0)
1081 return ret;
Al Viro72ec3512013-03-20 10:42:10 -04001082
Al Viro0504c072015-03-21 19:40:11 -04001083 tot_len = iov_iter_count(&iter);
1084 if (!tot_len)
1085 goto out;
Al Viro72ec3512013-03-20 10:42:10 -04001086 ret = rw_verify_area(type, file, pos, tot_len);
1087 if (ret < 0)
1088 goto out;
1089
Al Viro72ec3512013-03-20 10:42:10 -04001090 if (type == READ) {
1091 fn = file->f_op->read;
Al Viro293bc982014-02-11 18:37:41 -05001092 iter_fn = file->f_op->read_iter;
Al Viro72ec3512013-03-20 10:42:10 -04001093 } else {
1094 fn = (io_fn_t)file->f_op->write;
Al Viro293bc982014-02-11 18:37:41 -05001095 iter_fn = file->f_op->write_iter;
Al Viro03d95eb2013-03-20 13:04:20 -04001096 file_start_write(file);
Al Viro72ec3512013-03-20 10:42:10 -04001097 }
1098
Al Viro293bc982014-02-11 18:37:41 -05001099 if (iter_fn)
Christoph Hellwig793b80e2016-03-03 16:03:58 +01001100 ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags);
Al Viro03d95eb2013-03-20 13:04:20 -04001101 else
Christoph Hellwig793b80e2016-03-03 16:03:58 +01001102 ret = do_loop_readv_writev(file, &iter, pos, fn, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001103
Al Viro03d95eb2013-03-20 13:04:20 -04001104 if (type != READ)
1105 file_end_write(file);
1106
Al Viro72ec3512013-03-20 10:42:10 -04001107out:
Al Viro0504c072015-03-21 19:40:11 -04001108 kfree(iov);
Al Viro72ec3512013-03-20 10:42:10 -04001109 if ((ret + (type == READ)) > 0) {
1110 if (type == READ)
1111 fsnotify_access(file);
1112 else
1113 fsnotify_modify(file);
1114 }
1115 return ret;
1116}
1117
1118static size_t compat_readv(struct file *file,
1119 const struct compat_iovec __user *vec,
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001120 unsigned long vlen, loff_t *pos, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001121{
1122 ssize_t ret = -EBADF;
1123
1124 if (!(file->f_mode & FMODE_READ))
1125 goto out;
1126
1127 ret = -EINVAL;
Al Viro7f7f25e2014-02-11 17:49:24 -05001128 if (!(file->f_mode & FMODE_CAN_READ))
Al Viro72ec3512013-03-20 10:42:10 -04001129 goto out;
1130
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001131 ret = compat_do_readv_writev(READ, file, vec, vlen, pos, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001132
1133out:
1134 if (ret > 0)
1135 add_rchar(current, ret);
1136 inc_syscr(current);
1137 return ret;
1138}
1139
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001140static size_t do_compat_readv(compat_ulong_t fd,
1141 const struct compat_iovec __user *vec,
1142 compat_ulong_t vlen, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001143{
Linus Torvalds9c225f22014-03-03 09:36:58 -08001144 struct fd f = fdget_pos(fd);
Al Viro72ec3512013-03-20 10:42:10 -04001145 ssize_t ret;
1146 loff_t pos;
1147
1148 if (!f.file)
1149 return -EBADF;
1150 pos = f.file->f_pos;
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001151 ret = compat_readv(f.file, vec, vlen, &pos, flags);
Al Viro5faf1532013-06-15 05:49:36 +04001152 if (ret >= 0)
1153 f.file->f_pos = pos;
Linus Torvalds9c225f22014-03-03 09:36:58 -08001154 fdput_pos(f);
Al Viro72ec3512013-03-20 10:42:10 -04001155 return ret;
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001156
Al Viro72ec3512013-03-20 10:42:10 -04001157}
1158
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001159COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
1160 const struct compat_iovec __user *,vec,
1161 compat_ulong_t, vlen)
1162{
1163 return do_compat_readv(fd, vec, vlen, 0);
1164}
1165
1166static long do_compat_preadv64(unsigned long fd,
Heiko Carstens378a10f2014-03-05 10:43:51 +01001167 const struct compat_iovec __user *vec,
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001168 unsigned long vlen, loff_t pos, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001169{
1170 struct fd f;
1171 ssize_t ret;
1172
1173 if (pos < 0)
1174 return -EINVAL;
1175 f = fdget(fd);
1176 if (!f.file)
1177 return -EBADF;
1178 ret = -ESPIPE;
1179 if (f.file->f_mode & FMODE_PREAD)
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001180 ret = compat_readv(f.file, vec, vlen, &pos, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001181 fdput(f);
1182 return ret;
1183}
1184
Heiko Carstens378a10f2014-03-05 10:43:51 +01001185#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
1186COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
1187 const struct compat_iovec __user *,vec,
1188 unsigned long, vlen, loff_t, pos)
1189{
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001190 return do_compat_preadv64(fd, vec, vlen, pos, 0);
Heiko Carstens378a10f2014-03-05 10:43:51 +01001191}
1192#endif
1193
Heiko Carstensdfd948e2014-01-29 14:05:44 -08001194COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
Al Viro72ec3512013-03-20 10:42:10 -04001195 const struct compat_iovec __user *,vec,
Heiko Carstensdfd948e2014-01-29 14:05:44 -08001196 compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
Al Viro72ec3512013-03-20 10:42:10 -04001197{
1198 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
Heiko Carstens378a10f2014-03-05 10:43:51 +01001199
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001200 return do_compat_preadv64(fd, vec, vlen, pos, 0);
1201}
1202
H.J. Lu3ebfd812016-07-14 12:31:53 -07001203#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64V2
1204COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
1205 const struct compat_iovec __user *,vec,
1206 unsigned long, vlen, loff_t, pos, int, flags)
1207{
Aurelien Jarno24c6f9f2018-12-06 20:05:34 +01001208 if (pos == -1)
1209 return do_compat_readv(fd, vec, vlen, flags);
1210
H.J. Lu3ebfd812016-07-14 12:31:53 -07001211 return do_compat_preadv64(fd, vec, vlen, pos, flags);
1212}
1213#endif
1214
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001215COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd,
1216 const struct compat_iovec __user *,vec,
1217 compat_ulong_t, vlen, u32, pos_low, u32, pos_high,
1218 int, flags)
1219{
1220 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1221
1222 if (pos == -1)
1223 return do_compat_readv(fd, vec, vlen, flags);
1224
1225 return do_compat_preadv64(fd, vec, vlen, pos, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001226}
1227
1228static size_t compat_writev(struct file *file,
1229 const struct compat_iovec __user *vec,
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001230 unsigned long vlen, loff_t *pos, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001231{
1232 ssize_t ret = -EBADF;
1233
1234 if (!(file->f_mode & FMODE_WRITE))
1235 goto out;
1236
1237 ret = -EINVAL;
Al Viro7f7f25e2014-02-11 17:49:24 -05001238 if (!(file->f_mode & FMODE_CAN_WRITE))
Al Viro72ec3512013-03-20 10:42:10 -04001239 goto out;
1240
Christoph Hellwig222aa342017-06-16 11:08:24 +02001241 ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001242
1243out:
1244 if (ret > 0)
1245 add_wchar(current, ret);
1246 inc_syscw(current);
1247 return ret;
1248}
1249
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001250static size_t do_compat_writev(compat_ulong_t fd,
1251 const struct compat_iovec __user* vec,
1252 compat_ulong_t vlen, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001253{
Linus Torvalds9c225f22014-03-03 09:36:58 -08001254 struct fd f = fdget_pos(fd);
Al Viro72ec3512013-03-20 10:42:10 -04001255 ssize_t ret;
1256 loff_t pos;
1257
1258 if (!f.file)
1259 return -EBADF;
1260 pos = f.file->f_pos;
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001261 ret = compat_writev(f.file, vec, vlen, &pos, flags);
Al Viro5faf1532013-06-15 05:49:36 +04001262 if (ret >= 0)
1263 f.file->f_pos = pos;
Linus Torvalds9c225f22014-03-03 09:36:58 -08001264 fdput_pos(f);
Al Viro72ec3512013-03-20 10:42:10 -04001265 return ret;
1266}
1267
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001268COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
1269 const struct compat_iovec __user *, vec,
1270 compat_ulong_t, vlen)
1271{
1272 return do_compat_writev(fd, vec, vlen, 0);
1273}
1274
1275static long do_compat_pwritev64(unsigned long fd,
Heiko Carstens378a10f2014-03-05 10:43:51 +01001276 const struct compat_iovec __user *vec,
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001277 unsigned long vlen, loff_t pos, int flags)
Al Viro72ec3512013-03-20 10:42:10 -04001278{
1279 struct fd f;
1280 ssize_t ret;
1281
1282 if (pos < 0)
1283 return -EINVAL;
1284 f = fdget(fd);
1285 if (!f.file)
1286 return -EBADF;
1287 ret = -ESPIPE;
1288 if (f.file->f_mode & FMODE_PWRITE)
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001289 ret = compat_writev(f.file, vec, vlen, &pos, flags);
Al Viro72ec3512013-03-20 10:42:10 -04001290 fdput(f);
1291 return ret;
1292}
1293
Heiko Carstens378a10f2014-03-05 10:43:51 +01001294#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
1295COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
1296 const struct compat_iovec __user *,vec,
1297 unsigned long, vlen, loff_t, pos)
1298{
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001299 return do_compat_pwritev64(fd, vec, vlen, pos, 0);
Heiko Carstens378a10f2014-03-05 10:43:51 +01001300}
1301#endif
1302
Heiko Carstensdfd948e2014-01-29 14:05:44 -08001303COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
Al Viro72ec3512013-03-20 10:42:10 -04001304 const struct compat_iovec __user *,vec,
Heiko Carstensdfd948e2014-01-29 14:05:44 -08001305 compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
Al Viro72ec3512013-03-20 10:42:10 -04001306{
1307 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
Heiko Carstens378a10f2014-03-05 10:43:51 +01001308
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001309 return do_compat_pwritev64(fd, vec, vlen, pos, 0);
Al Viro72ec3512013-03-20 10:42:10 -04001310}
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001311
H.J. Lu3ebfd812016-07-14 12:31:53 -07001312#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64V2
1313COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
1314 const struct compat_iovec __user *,vec,
1315 unsigned long, vlen, loff_t, pos, int, flags)
1316{
Aurelien Jarno24c6f9f2018-12-06 20:05:34 +01001317 if (pos == -1)
1318 return do_compat_writev(fd, vec, vlen, flags);
1319
H.J. Lu3ebfd812016-07-14 12:31:53 -07001320 return do_compat_pwritev64(fd, vec, vlen, pos, flags);
1321}
1322#endif
1323
Milosz Tanskif17d8b32016-03-03 16:03:59 +01001324COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
1325 const struct compat_iovec __user *,vec,
1326 compat_ulong_t, vlen, u32, pos_low, u32, pos_high, int, flags)
1327{
1328 loff_t pos = ((loff_t)pos_high << 32) | pos_low;
1329
1330 if (pos == -1)
1331 return do_compat_writev(fd, vec, vlen, flags);
1332
1333 return do_compat_pwritev64(fd, vec, vlen, pos, flags);
1334}
1335
Al Viro72ec3512013-03-20 10:42:10 -04001336#endif
1337
Al Viro19f4fc32013-02-24 02:17:03 -05001338static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
1339 size_t count, loff_t max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Al Viro2903ff02012-08-28 12:52:22 -04001341 struct fd in, out;
1342 struct inode *in_inode, *out_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 loff_t pos;
Al Viro7995bd22013-06-20 18:58:36 +04001344 loff_t out_pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 ssize_t retval;
Al Viro2903ff02012-08-28 12:52:22 -04001346 int fl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
1348 /*
1349 * Get input file, and verify that it is ok..
1350 */
1351 retval = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -04001352 in = fdget(in_fd);
1353 if (!in.file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 goto out;
Al Viro2903ff02012-08-28 12:52:22 -04001355 if (!(in.file->f_mode & FMODE_READ))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 goto fput_in;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 retval = -ESPIPE;
Al Viro7995bd22013-06-20 18:58:36 +04001358 if (!ppos) {
1359 pos = in.file->f_pos;
1360 } else {
1361 pos = *ppos;
Al Viro2903ff02012-08-28 12:52:22 -04001362 if (!(in.file->f_mode & FMODE_PREAD))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 goto fput_in;
Al Viro7995bd22013-06-20 18:58:36 +04001364 }
1365 retval = rw_verify_area(READ, in.file, &pos, count);
Linus Torvaldse28cc712006-01-04 16:20:40 -08001366 if (retval < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 goto fput_in;
Al Virobc613842016-03-31 21:48:20 -04001368 if (count > MAX_RW_COUNT)
1369 count = MAX_RW_COUNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 /*
1372 * Get output file, and verify that it is ok..
1373 */
1374 retval = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -04001375 out = fdget(out_fd);
1376 if (!out.file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 goto fput_in;
Al Viro2903ff02012-08-28 12:52:22 -04001378 if (!(out.file->f_mode & FMODE_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 goto fput_out;
1380 retval = -EINVAL;
Al Viro496ad9a2013-01-23 17:07:38 -05001381 in_inode = file_inode(in.file);
1382 out_inode = file_inode(out.file);
Al Viro7995bd22013-06-20 18:58:36 +04001383 out_pos = out.file->f_pos;
1384 retval = rw_verify_area(WRITE, out.file, &out_pos, count);
Linus Torvaldse28cc712006-01-04 16:20:40 -08001385 if (retval < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 goto fput_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 if (!max)
1389 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
1390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 if (unlikely(pos + count > max)) {
1392 retval = -EOVERFLOW;
1393 if (pos >= max)
1394 goto fput_out;
1395 count = max - pos;
1396 }
1397
Jens Axboed96e6e72007-06-11 12:18:52 +02001398 fl = 0;
Jens Axboe534f2aa2007-06-01 14:52:37 +02001399#if 0
Jens Axboed96e6e72007-06-11 12:18:52 +02001400 /*
1401 * We need to debate whether we can enable this or not. The
1402 * man page documents EAGAIN return for the output at least,
1403 * and the application is arguably buggy if it doesn't expect
1404 * EAGAIN on a non-blocking file descriptor.
1405 */
Al Viro2903ff02012-08-28 12:52:22 -04001406 if (in.file->f_flags & O_NONBLOCK)
Jens Axboed96e6e72007-06-11 12:18:52 +02001407 fl = SPLICE_F_NONBLOCK;
Jens Axboe534f2aa2007-06-01 14:52:37 +02001408#endif
Al Viro50cd2c52013-05-23 20:10:34 -04001409 file_start_write(out.file);
Al Viro7995bd22013-06-20 18:58:36 +04001410 retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl);
Al Viro50cd2c52013-05-23 20:10:34 -04001411 file_end_write(out.file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 if (retval > 0) {
Alexey Dobriyan4b98d112007-02-10 01:46:45 -08001414 add_rchar(current, retval);
1415 add_wchar(current, retval);
Scott Wolchoka68c2f12012-12-20 15:05:52 -08001416 fsnotify_access(in.file);
1417 fsnotify_modify(out.file);
Al Viro7995bd22013-06-20 18:58:36 +04001418 out.file->f_pos = out_pos;
1419 if (ppos)
1420 *ppos = pos;
1421 else
1422 in.file->f_pos = pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Alexey Dobriyan4b98d112007-02-10 01:46:45 -08001425 inc_syscr(current);
1426 inc_syscw(current);
Al Viro7995bd22013-06-20 18:58:36 +04001427 if (pos > max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 retval = -EOVERFLOW;
1429
1430fput_out:
Al Viro2903ff02012-08-28 12:52:22 -04001431 fdput(out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432fput_in:
Al Viro2903ff02012-08-28 12:52:22 -04001433 fdput(in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434out:
1435 return retval;
1436}
1437
Heiko Carstens002c8972009-01-14 14:14:18 +01001438SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
1440 loff_t pos;
1441 off_t off;
1442 ssize_t ret;
1443
1444 if (offset) {
1445 if (unlikely(get_user(off, offset)))
1446 return -EFAULT;
1447 pos = off;
1448 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
1449 if (unlikely(put_user(pos, offset)))
1450 return -EFAULT;
1451 return ret;
1452 }
1453
1454 return do_sendfile(out_fd, in_fd, NULL, count, 0);
1455}
1456
Heiko Carstens002c8972009-01-14 14:14:18 +01001457SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458{
1459 loff_t pos;
1460 ssize_t ret;
1461
1462 if (offset) {
1463 if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
1464 return -EFAULT;
1465 ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
1466 if (unlikely(put_user(pos, offset)))
1467 return -EFAULT;
1468 return ret;
1469 }
1470
1471 return do_sendfile(out_fd, in_fd, NULL, count, 0);
1472}
Al Viro19f4fc32013-02-24 02:17:03 -05001473
1474#ifdef CONFIG_COMPAT
1475COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
1476 compat_off_t __user *, offset, compat_size_t, count)
1477{
1478 loff_t pos;
1479 off_t off;
1480 ssize_t ret;
1481
1482 if (offset) {
1483 if (unlikely(get_user(off, offset)))
1484 return -EFAULT;
1485 pos = off;
1486 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
1487 if (unlikely(put_user(pos, offset)))
1488 return -EFAULT;
1489 return ret;
1490 }
1491
1492 return do_sendfile(out_fd, in_fd, NULL, count, 0);
1493}
1494
1495COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
1496 compat_loff_t __user *, offset, compat_size_t, count)
1497{
1498 loff_t pos;
1499 ssize_t ret;
1500
1501 if (offset) {
1502 if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
1503 return -EFAULT;
1504 ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
1505 if (unlikely(put_user(pos, offset)))
1506 return -EFAULT;
1507 return ret;
1508 }
1509
1510 return do_sendfile(out_fd, in_fd, NULL, count, 0);
1511}
1512#endif
Zach Brown29732932015-11-10 16:53:30 -05001513
1514/*
1515 * copy_file_range() differs from regular file read and write in that it
1516 * specifically allows return partial success. When it does so is up to
1517 * the copy_file_range method.
1518 */
1519ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1520 struct file *file_out, loff_t pos_out,
1521 size_t len, unsigned int flags)
1522{
1523 struct inode *inode_in = file_inode(file_in);
1524 struct inode *inode_out = file_inode(file_out);
1525 ssize_t ret;
1526
1527 if (flags != 0)
1528 return -EINVAL;
1529
Amir Goldstein27db1f02017-01-31 10:34:56 +02001530 if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
1531 return -EISDIR;
1532 if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
1533 return -EINVAL;
1534
Zach Brown29732932015-11-10 16:53:30 -05001535 ret = rw_verify_area(READ, file_in, &pos_in, len);
Al Virobc613842016-03-31 21:48:20 -04001536 if (unlikely(ret))
1537 return ret;
1538
1539 ret = rw_verify_area(WRITE, file_out, &pos_out, len);
1540 if (unlikely(ret))
Zach Brown29732932015-11-10 16:53:30 -05001541 return ret;
1542
1543 if (!(file_in->f_mode & FMODE_READ) ||
1544 !(file_out->f_mode & FMODE_WRITE) ||
Anna Schumakereac70052015-11-10 16:53:33 -05001545 (file_out->f_flags & O_APPEND))
Zach Brown29732932015-11-10 16:53:30 -05001546 return -EBADF;
1547
1548 /* this could be relaxed once a method supports cross-fs copies */
1549 if (inode_in->i_sb != inode_out->i_sb)
1550 return -EXDEV;
1551
1552 if (len == 0)
1553 return 0;
1554
1555 ret = mnt_want_write_file(file_out);
1556 if (ret)
1557 return ret;
1558
Anna Schumakereac70052015-11-10 16:53:33 -05001559 ret = -EOPNOTSUPP;
1560 if (file_out->f_op->copy_file_range)
1561 ret = file_out->f_op->copy_file_range(file_in, pos_in, file_out,
1562 pos_out, len, flags);
1563 if (ret == -EOPNOTSUPP)
1564 ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
1565 len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
1566
Zach Brown29732932015-11-10 16:53:30 -05001567 if (ret > 0) {
1568 fsnotify_access(file_in);
1569 add_rchar(current, ret);
1570 fsnotify_modify(file_out);
1571 add_wchar(current, ret);
1572 }
1573 inc_syscr(current);
1574 inc_syscw(current);
1575
1576 mnt_drop_write_file(file_out);
1577
1578 return ret;
1579}
1580EXPORT_SYMBOL(vfs_copy_file_range);
1581
1582SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
1583 int, fd_out, loff_t __user *, off_out,
1584 size_t, len, unsigned int, flags)
1585{
1586 loff_t pos_in;
1587 loff_t pos_out;
1588 struct fd f_in;
1589 struct fd f_out;
1590 ssize_t ret = -EBADF;
1591
1592 f_in = fdget(fd_in);
1593 if (!f_in.file)
1594 goto out2;
1595
1596 f_out = fdget(fd_out);
1597 if (!f_out.file)
1598 goto out1;
1599
1600 ret = -EFAULT;
1601 if (off_in) {
1602 if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
1603 goto out;
1604 } else {
1605 pos_in = f_in.file->f_pos;
1606 }
1607
1608 if (off_out) {
1609 if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
1610 goto out;
1611 } else {
1612 pos_out = f_out.file->f_pos;
1613 }
1614
1615 ret = vfs_copy_file_range(f_in.file, pos_in, f_out.file, pos_out, len,
1616 flags);
1617 if (ret > 0) {
1618 pos_in += ret;
1619 pos_out += ret;
1620
1621 if (off_in) {
1622 if (copy_to_user(off_in, &pos_in, sizeof(loff_t)))
1623 ret = -EFAULT;
1624 } else {
1625 f_in.file->f_pos = pos_in;
1626 }
1627
1628 if (off_out) {
1629 if (copy_to_user(off_out, &pos_out, sizeof(loff_t)))
1630 ret = -EFAULT;
1631 } else {
1632 f_out.file->f_pos = pos_out;
1633 }
1634 }
1635
1636out:
1637 fdput(f_out);
1638out1:
1639 fdput(f_in);
1640out2:
1641 return ret;
1642}
Christoph Hellwig04b38d62015-12-03 12:59:50 +01001643
1644static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write)
1645{
1646 struct inode *inode = file_inode(file);
1647
1648 if (unlikely(pos < 0))
1649 return -EINVAL;
1650
1651 if (unlikely((loff_t) (pos + len) < 0))
1652 return -EINVAL;
1653
1654 if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
1655 loff_t end = len ? pos + len - 1 : OFFSET_MAX;
1656 int retval;
1657
1658 retval = locks_mandatory_area(inode, file, pos, end,
1659 write ? F_WRLCK : F_RDLCK);
1660 if (retval < 0)
1661 return retval;
1662 }
1663
1664 return security_file_permission(file, write ? MAY_WRITE : MAY_READ);
1665}
1666
1667int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
1668 struct file *file_out, loff_t pos_out, u64 len)
1669{
1670 struct inode *inode_in = file_inode(file_in);
1671 struct inode *inode_out = file_inode(file_out);
1672 int ret;
1673
1674 if (inode_in->i_sb != inode_out->i_sb ||
1675 file_in->f_path.mnt != file_out->f_path.mnt)
1676 return -EXDEV;
1677
1678 if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
1679 return -EISDIR;
1680 if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
Darrick J. Wongd79bdd52015-12-19 00:55:52 -08001681 return -EINVAL;
Christoph Hellwig04b38d62015-12-03 12:59:50 +01001682
1683 if (!(file_in->f_mode & FMODE_READ) ||
1684 !(file_out->f_mode & FMODE_WRITE) ||
Christoph Hellwig0fcbf992016-02-26 18:53:12 +01001685 (file_out->f_flags & O_APPEND))
Christoph Hellwig04b38d62015-12-03 12:59:50 +01001686 return -EBADF;
1687
Christoph Hellwig0fcbf992016-02-26 18:53:12 +01001688 if (!file_in->f_op->clone_file_range)
1689 return -EOPNOTSUPP;
1690
Christoph Hellwig04b38d62015-12-03 12:59:50 +01001691 ret = clone_verify_area(file_in, pos_in, len, false);
1692 if (ret)
1693 return ret;
1694
1695 ret = clone_verify_area(file_out, pos_out, len, true);
1696 if (ret)
1697 return ret;
1698
1699 if (pos_in + len > i_size_read(inode_in))
1700 return -EINVAL;
1701
1702 ret = mnt_want_write_file(file_out);
1703 if (ret)
1704 return ret;
1705
1706 ret = file_in->f_op->clone_file_range(file_in, pos_in,
1707 file_out, pos_out, len);
1708 if (!ret) {
1709 fsnotify_access(file_in);
1710 fsnotify_modify(file_out);
1711 }
1712
1713 mnt_drop_write_file(file_out);
1714 return ret;
1715}
1716EXPORT_SYMBOL(vfs_clone_file_range);
Darrick J. Wong54dbc152015-12-19 00:55:59 -08001717
1718int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
1719{
1720 struct file_dedupe_range_info *info;
1721 struct inode *src = file_inode(file);
1722 u64 off;
1723 u64 len;
1724 int i;
1725 int ret;
1726 bool is_admin = capable(CAP_SYS_ADMIN);
1727 u16 count = same->dest_count;
1728 struct file *dst_file;
1729 loff_t dst_off;
1730 ssize_t deduped;
1731
1732 if (!(file->f_mode & FMODE_READ))
1733 return -EINVAL;
1734
1735 if (same->reserved1 || same->reserved2)
1736 return -EINVAL;
1737
1738 off = same->src_offset;
1739 len = same->src_length;
1740
1741 ret = -EISDIR;
1742 if (S_ISDIR(src->i_mode))
1743 goto out;
1744
1745 ret = -EINVAL;
1746 if (!S_ISREG(src->i_mode))
1747 goto out;
1748
1749 ret = clone_verify_area(file, off, len, false);
1750 if (ret < 0)
1751 goto out;
1752 ret = 0;
1753
1754 /* pre-format output fields to sane values */
1755 for (i = 0; i < count; i++) {
1756 same->info[i].bytes_deduped = 0ULL;
1757 same->info[i].status = FILE_DEDUPE_RANGE_SAME;
1758 }
1759
1760 for (i = 0, info = same->info; i < count; i++, info++) {
1761 struct inode *dst;
1762 struct fd dst_fd = fdget(info->dest_fd);
1763
1764 dst_file = dst_fd.file;
1765 if (!dst_file) {
1766 info->status = -EBADF;
1767 goto next_loop;
1768 }
1769 dst = file_inode(dst_file);
1770
1771 ret = mnt_want_write_file(dst_file);
1772 if (ret) {
1773 info->status = ret;
1774 goto next_loop;
1775 }
1776
1777 dst_off = info->dest_offset;
1778 ret = clone_verify_area(dst_file, dst_off, len, true);
1779 if (ret < 0) {
1780 info->status = ret;
1781 goto next_file;
1782 }
1783 ret = 0;
1784
1785 if (info->reserved) {
1786 info->status = -EINVAL;
1787 } else if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
1788 info->status = -EINVAL;
1789 } else if (file->f_path.mnt != dst_file->f_path.mnt) {
1790 info->status = -EXDEV;
1791 } else if (S_ISDIR(dst->i_mode)) {
1792 info->status = -EISDIR;
1793 } else if (dst_file->f_op->dedupe_file_range == NULL) {
1794 info->status = -EINVAL;
1795 } else {
1796 deduped = dst_file->f_op->dedupe_file_range(file, off,
1797 len, dst_file,
1798 info->dest_offset);
1799 if (deduped == -EBADE)
1800 info->status = FILE_DEDUPE_RANGE_DIFFERS;
1801 else if (deduped < 0)
1802 info->status = deduped;
1803 else
1804 info->bytes_deduped += deduped;
1805 }
1806
1807next_file:
1808 mnt_drop_write_file(dst_file);
1809next_loop:
1810 fdput(dst_fd);
Darrick J. Wonge62e5602016-01-22 16:58:28 -08001811
1812 if (fatal_signal_pending(current))
1813 goto out;
Darrick J. Wong54dbc152015-12-19 00:55:59 -08001814 }
1815
1816out:
1817 return ret;
1818}
1819EXPORT_SYMBOL(vfs_dedupe_file_range);