b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/read_write.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1991, 1992 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7)
b12fb7f46af7d (Ingo Molnar 2017-02-08 18:51:33 +0100 8) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/stat.h>
b12fb7f46af7d (Ingo Molnar 2017-02-08 18:51:33 +0100 10) #include <linux/sched/xacct.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/fcntl.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/uio.h>
0eeca28300df1 (Robert Love 2005-07-12 17:06:03 -0400 14) #include <linux/fsnotify.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/security.h>
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 16) #include <linux/export.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) #include <linux/syscalls.h>
e28cc71572da3 (Linus Torvalds 2006-01-04 16:20:40 -0800 18) #include <linux/pagemap.h>
d6b29d7cee064 (Jens Axboe 2007-06-04 09:59:47 +0200 19) #include <linux/splice.h>
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 20) #include <linux/compat.h>
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 21) #include <linux/mount.h>
2feb55f89096b (Wouter van Kesteren 2016-02-16 22:20:59 +0100 22) #include <linux/fs.h>
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 23) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24)
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 25) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) #include <asm/unistd.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 28) const struct file_operations generic_ro_fops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) .llseek = generic_file_llseek,
aad4f8bb42af0 (Al Viro 2014-04-02 14:33:16 -0400 30) .read_iter = generic_file_read_iter,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) .mmap = generic_file_readonly_mmap,
534f2aaa6ab07 (Jens Axboe 2007-06-01 14:52:37 +0200 32) .splice_read = generic_file_splice_read,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) EXPORT_SYMBOL(generic_ro_fops);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36)
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 37) static inline bool unsigned_offsets(struct file *file)
4a3956c790290 (KAMEZAWA Hiroyuki 2010-10-01 14:20:22 -0700 38) {
cccb5a1e69853 (Al Viro 2010-12-17 07:44:05 -0500 39) return file->f_mode & FMODE_UNSIGNED_OFFSET;
4a3956c790290 (KAMEZAWA Hiroyuki 2010-10-01 14:20:22 -0700 40) }
4a3956c790290 (KAMEZAWA Hiroyuki 2010-10-01 14:20:22 -0700 41)
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 42) /**
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 43) * vfs_setpos - update the file offset for lseek
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 44) * @file: file structure in question
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 45) * @offset: file offset to seek to
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 46) * @maxsize: maximum file size
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 47) *
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 48) * This is a low-level filesystem helper for updating the file offset to
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 49) * the value specified by @offset if the given offset is valid and it is
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 50) * not equal to the current file offset.
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 51) *
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 52) * Return the specified offset on success and -EINVAL on invalid offset.
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 53) */
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 54) loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 55) {
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 56) if (offset < 0 && !unsigned_offsets(file))
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 57) return -EINVAL;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 58) if (offset > maxsize)
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 59) return -EINVAL;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 60)
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 61) if (offset != file->f_pos) {
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 62) file->f_pos = offset;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 63) file->f_version = 0;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 64) }
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 65) return offset;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 66) }
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 67) EXPORT_SYMBOL(vfs_setpos);
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 68)
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 69) /**
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 70) * generic_file_llseek_size - generic llseek implementation for regular files
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 71) * @file: file structure to seek on
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 72) * @offset: file offset to seek to
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 73) * @whence: type of seek
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 74) * @size: max size of this file in file system
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 75) * @eof: offset used for SEEK_END position
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 76) *
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 77) * This is a variant of generic_file_llseek that allows passing in a custom
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 78) * maximum file size and a custom EOF position, for e.g. hashed directories
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 79) *
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 80) * Synchronization:
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 81) * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 82) * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes.
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 83) * read/writes behave like SEEK_SET against seeks.
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 84) */
9465efc9e9613 (Andi Kleen 2008-06-27 11:05:24 +0200 85) loff_t
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 86) generic_file_llseek_size(struct file *file, loff_t offset, int whence,
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 87) loff_t maxsize, loff_t eof)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) {
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 89) switch (whence) {
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 90) case SEEK_END:
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 91) offset += eof;
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 92) break;
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 93) case SEEK_CUR:
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 94) /*
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 95) * Here we special-case the lseek(fd, 0, SEEK_CUR)
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 96) * position-querying operation. Avoid rewriting the "same"
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 97) * f_pos value back to the file because a concurrent read(),
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 98) * write() or lseek() might have altered it
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 99) */
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 100) if (offset == 0)
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 101) return file->f_pos;
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 102) /*
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 103) * f_lock protects against read/modify/write race with other
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 104) * SEEK_CURs. Note that parallel writes and reads behave
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 105) * like SEEK_SET.
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 106) */
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 107) spin_lock(&file->f_lock);
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 108) offset = vfs_setpos(file, file->f_pos + offset, maxsize);
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 109) spin_unlock(&file->f_lock);
ef3d0fd27e90f (Andi Kleen 2011-09-15 16:06:48 -0700 110) return offset;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 111) case SEEK_DATA:
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 112) /*
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 113) * In the generic case the entire file is data, so as long as
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 114) * offset isn't at the end of the file then the offset is data.
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 115) */
fc46820b27a2d (Andreas Gruenbacher 2017-09-25 12:23:03 +0200 116) if ((unsigned long long)offset >= eof)
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 117) return -ENXIO;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 118) break;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 119) case SEEK_HOLE:
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 120) /*
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 121) * There is a virtual hole at the end of the file, so as long as
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 122) * offset isn't i_size or larger, return i_size.
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 123) */
fc46820b27a2d (Andreas Gruenbacher 2017-09-25 12:23:03 +0200 124) if ((unsigned long long)offset >= eof)
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 125) return -ENXIO;
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 126) offset = eof;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 127) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) }
3a8cff4f026c0 (Christoph Hellwig 2008-08-11 15:37:17 +0200 129)
46a1c2c7ae53d (Jie Liu 2013-06-25 12:02:13 +0800 130) return vfs_setpos(file, offset, maxsize);
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 131) }
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 132) EXPORT_SYMBOL(generic_file_llseek_size);
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 133)
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 134) /**
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 135) * generic_file_llseek - generic llseek implementation for regular files
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 136) * @file: file structure to seek on
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 137) * @offset: file offset to seek to
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 138) * @whence: type of seek
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 139) *
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 140) * This is a generic implemenation of ->llseek useable for all normal local
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 141) * filesystems. It just updates the file offset to the value specified by
546ae2d2f7172 (Ming Lei 2013-04-29 15:06:07 -0700 142) * @offset and @whence.
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 143) */
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 144) loff_t generic_file_llseek(struct file *file, loff_t offset, int whence)
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 145) {
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 146) struct inode *inode = file->f_mapping->host;
5760495a872d6 (Andi Kleen 2011-09-15 16:06:50 -0700 147)
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 148) return generic_file_llseek_size(file, offset, whence,
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 149) inode->i_sb->s_maxbytes,
e8b96eb5034a0 (Eric Sandeen 2012-04-30 13:11:29 -0500 150) i_size_read(inode));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) }
9465efc9e9613 (Andi Kleen 2008-06-27 11:05:24 +0200 152) EXPORT_SYMBOL(generic_file_llseek);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153)
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 154) /**
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 155) * fixed_size_llseek - llseek implementation for fixed-sized devices
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 156) * @file: file structure to seek on
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 157) * @offset: file offset to seek to
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 158) * @whence: type of seek
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 159) * @size: size of the file
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 160) *
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 161) */
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 162) loff_t fixed_size_llseek(struct file *file, loff_t offset, int whence, loff_t size)
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 163) {
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 164) switch (whence) {
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 165) case SEEK_SET: case SEEK_CUR: case SEEK_END:
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 166) return generic_file_llseek_size(file, offset, whence,
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 167) size, size);
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 168) default:
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 169) return -EINVAL;
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 170) }
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 171) }
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 172) EXPORT_SYMBOL(fixed_size_llseek);
1bf9d14dff4a2 (Al Viro 2013-06-16 20:27:42 +0400 173)
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 174) /**
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 175) * no_seek_end_llseek - llseek implementation for fixed-sized devices
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 176) * @file: file structure to seek on
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 177) * @offset: file offset to seek to
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 178) * @whence: type of seek
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 179) *
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 180) */
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 181) loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 182) {
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 183) switch (whence) {
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 184) case SEEK_SET: case SEEK_CUR:
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 185) return generic_file_llseek_size(file, offset, whence,
2feb55f89096b (Wouter van Kesteren 2016-02-16 22:20:59 +0100 186) OFFSET_MAX, 0);
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 187) default:
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 188) return -EINVAL;
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 189) }
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 190) }
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 191) EXPORT_SYMBOL(no_seek_end_llseek);
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 192)
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 193) /**
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 194) * no_seek_end_llseek_size - llseek implementation for fixed-sized devices
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 195) * @file: file structure to seek on
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 196) * @offset: file offset to seek to
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 197) * @whence: type of seek
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 198) * @size: maximal offset allowed
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 199) *
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 200) */
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 201) loff_t no_seek_end_llseek_size(struct file *file, loff_t offset, int whence, loff_t size)
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 202) {
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 203) switch (whence) {
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 204) case SEEK_SET: case SEEK_CUR:
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 205) return generic_file_llseek_size(file, offset, whence,
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 206) size, 0);
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 207) default:
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 208) return -EINVAL;
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 209) }
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 210) }
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 211) EXPORT_SYMBOL(no_seek_end_llseek_size);
b25472f9b9615 (Al Viro 2015-12-05 22:04:48 -0500 212)
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 213) /**
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 214) * noop_llseek - No Operation Performed llseek implementation
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 215) * @file: file structure to seek on
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 216) * @offset: file offset to seek to
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 217) * @whence: type of seek
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 218) *
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 219) * This is an implementation of ->llseek useable for the rare special case when
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 220) * userspace expects the seek to succeed but the (device) file is actually not
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 221) * able to perform the seek. In this case you use noop_llseek() instead of
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 222) * falling back to the default implementation of ->llseek.
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 223) */
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 224) loff_t noop_llseek(struct file *file, loff_t offset, int whence)
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 225) {
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 226) return file->f_pos;
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 227) }
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 228) EXPORT_SYMBOL(noop_llseek);
ae6afc3f5cf53 (jan Blunck 2010-05-26 14:44:48 -0700 229)
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 230) loff_t no_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) return -ESPIPE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) EXPORT_SYMBOL(no_llseek);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235)
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 236) loff_t default_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 238) struct inode *inode = file_inode(file);
16abef0e9e796 (David Sterba 2008-04-22 15:09:22 +0200 239) loff_t retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 241) inode_lock(inode);
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 242) switch (whence) {
7b8e89249ba54 (Chris Snook 2007-05-08 00:24:13 -0700 243) case SEEK_END:
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 244) offset += i_size_read(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 245) break;
7b8e89249ba54 (Chris Snook 2007-05-08 00:24:13 -0700 246) case SEEK_CUR:
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 247) if (offset == 0) {
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 248) retval = file->f_pos;
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 249) goto out;
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 250) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) offset += file->f_pos;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 252) break;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 253) case SEEK_DATA:
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 254) /*
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 255) * In the generic case the entire file is data, so as
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 256) * long as offset isn't at the end of the file then the
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 257) * offset is data.
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 258) */
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 259) if (offset >= inode->i_size) {
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 260) retval = -ENXIO;
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 261) goto out;
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 262) }
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 263) break;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 264) case SEEK_HOLE:
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 265) /*
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 266) * There is a virtual hole at the end of the file, so
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 267) * as long as offset isn't i_size or larger, return
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 268) * i_size.
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 269) */
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 270) if (offset >= inode->i_size) {
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 271) retval = -ENXIO;
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 272) goto out;
bacb2d816c77e (Dan Carpenter 2011-07-26 17:25:20 +0300 273) }
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 274) offset = inode->i_size;
982d816581eee (Josef Bacik 2011-07-18 13:21:35 -0400 275) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) retval = -EINVAL;
cccb5a1e69853 (Al Viro 2010-12-17 07:44:05 -0500 278) if (offset >= 0 || unsigned_offsets(file)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 279) if (offset != file->f_pos) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) file->f_pos = offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281) file->f_version = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 282) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) retval = offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 284) }
5b6f1eb97d462 (Alain Knaff 2008-11-10 17:08:08 -0800 285) out:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 286) inode_unlock(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 289) EXPORT_SYMBOL(default_llseek);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290)
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 291) loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) loff_t (*fn)(struct file *, loff_t, int);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295) fn = no_llseek;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) if (file->f_mode & FMODE_LSEEK) {
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 297) if (file->f_op->llseek)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 298) fn = file->f_op->llseek;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 299) }
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 300) return fn(file, offset, whence);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) EXPORT_SYMBOL(vfs_llseek);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303)
bef1732996134 (Christoph Hellwig 2020-06-06 14:49:58 +0200 304) static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) off_t retval;
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 307) struct fd f = fdget_pos(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 308) if (!f.file)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 309) return -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) retval = -EINVAL;
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 312) if (whence <= SEEK_MAX) {
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 313) loff_t res = vfs_llseek(f.file, offset, whence);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314) retval = res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) if (res != (loff_t)retval)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) }
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 318) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 319) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321)
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 322) SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 323) {
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 324) return ksys_lseek(fd, offset, whence);
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 325) }
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 326)
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 327) #ifdef CONFIG_COMPAT
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 328) COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence)
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 329) {
76847e4344350 (Dominik Brodowski 2018-03-13 21:51:17 +0100 330) return ksys_lseek(fd, offset, whence);
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 331) }
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 332) #endif
561c6731978fa (Al Viro 2013-02-24 10:52:26 -0500 333)
9e62ccec3ba0a (Michal Suchanek 2020-03-20 11:20:12 +0100 334) #if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || \
9e62ccec3ba0a (Michal Suchanek 2020-03-20 11:20:12 +0100 335) defined(__ARCH_WANT_SYS_LLSEEK)
003d7ab479168 (Heiko Carstens 2009-01-14 14:14:21 +0100 336) SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
003d7ab479168 (Heiko Carstens 2009-01-14 14:14:21 +0100 337) unsigned long, offset_low, loff_t __user *, result,
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 338) unsigned int, whence)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 339) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 340) int retval;
d7a15f8d07779 (Eric Biggers 2014-03-16 14:24:08 -0500 341) struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 342) loff_t offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 344) if (!f.file)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 345) return -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 347) retval = -EINVAL;
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 348) if (whence > SEEK_MAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) goto out_putf;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 351) offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low,
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 352) whence);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 353)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 354) retval = (int)offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355) if (offset >= 0) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) retval = -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 357) if (!copy_to_user(result, &offset, sizeof(offset)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) retval = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) out_putf:
d7a15f8d07779 (Eric Biggers 2014-03-16 14:24:08 -0500 361) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 362) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 363) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 364) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 365)
68d70d03f8f5b (Al Viro 2013-06-19 15:26:04 +0400 366) int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 367) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 368) struct inode *inode;
c43e259cc756e (James Morris 2008-01-12 22:05:48 +1100 369) int retval = -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 370)
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 371) inode = file_inode(file);
e28cc71572da3 (Linus Torvalds 2006-01-04 16:20:40 -0800 372) if (unlikely((ssize_t) count < 0))
c43e259cc756e (James Morris 2008-01-12 22:05:48 +1100 373) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 374)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 375) /*
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 376) * ranged mandatory locking does not apply to streams - it makes sense
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 377) * only for files where position has a meaning.
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 378) */
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 379) if (ppos) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 380) loff_t pos = *ppos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 381)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 382) if (unlikely(pos < 0)) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 383) if (!unsigned_offsets(file))
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 384) return retval;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 385) if (count >= -pos) /* both values are in 0..LLONG_MAX */
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 386) return -EOVERFLOW;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 387) } else if (unlikely((loff_t) (pos + count) < 0)) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 388) if (!unsigned_offsets(file))
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 389) return retval;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 390) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 391)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 392) if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 393) retval = locks_mandatory_area(inode, file, pos, pos + count - 1,
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 394) read_write == READ ? F_RDLCK : F_WRLCK);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 395) if (retval < 0)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 396) return retval;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 397) }
e28cc71572da3 (Linus Torvalds 2006-01-04 16:20:40 -0800 398) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 399)
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 400) return security_file_permission(file,
c43e259cc756e (James Morris 2008-01-12 22:05:48 +1100 401) read_write == READ ? MAY_READ : MAY_WRITE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 402) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403)
5d5d568975307 (Al Viro 2015-04-03 15:41:18 -0400 404) static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 405) {
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 406) struct iovec iov = { .iov_base = buf, .iov_len = len };
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 407) struct kiocb kiocb;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 408) struct iov_iter iter;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 409) ssize_t ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 410)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 411) init_sync_kiocb(&kiocb, filp);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 412) kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 413) iov_iter_init(&iter, READ, &iov, 1, len);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 414)
bb7462b6fd64e (Miklos Szeredi 2017-02-20 16:51:23 +0100 415) ret = call_read_iter(filp, &kiocb, &iter);
599bd19bdc4c6 (Christoph Hellwig 2015-02-11 19:59:44 +0100 416) BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 417) if (ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 418) *ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 419) return ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 420) }
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 421)
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 422) static int warn_unsupported(struct file *file, const char *op)
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 423) {
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 424) pr_warn_ratelimited(
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 425) "kernel %s not supported for file %pD4 (pid: %d comm: %.20s)\n",
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 426) op, file, current->pid, current->comm);
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 427) return -EINVAL;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 428) }
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 429)
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 430) ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 431) {
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 432) struct kvec iov = {
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 433) .iov_base = buf,
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 434) .iov_len = min_t(size_t, count, MAX_RW_COUNT),
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 435) };
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 436) struct kiocb kiocb;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 437) struct iov_iter iter;
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 438) ssize_t ret;
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 439)
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 440) if (WARN_ON_ONCE(!(file->f_mode & FMODE_READ)))
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 441) return -EINVAL;
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 442) if (!(file->f_mode & FMODE_CAN_READ))
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 443) return -EINVAL;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 444) /*
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 445) * Also fail if ->read_iter and ->read are both wired up as that
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 446) * implies very convoluted semantics.
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 447) */
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 448) if (unlikely(!file->f_op->read_iter || file->f_op->read))
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 449) return warn_unsupported(file, "read");
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 450)
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 451) init_sync_kiocb(&kiocb, file);
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100 452) kiocb.ki_pos = pos ? *pos : 0;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 453) iov_iter_kvec(&iter, READ, &iov, 1, iov.iov_len);
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 454) ret = file->f_op->read_iter(&kiocb, &iter);
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 455) if (ret > 0) {
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100 456) if (pos)
7b84b665c874f (Matthew Wilcox (Oracle) 2020-10-03 03:55:23 +0100 457) *pos = kiocb.ki_pos;
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 458) fsnotify_access(file);
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 459) add_rchar(current, ret);
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 460) }
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 461) inc_syscr(current);
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 462) return ret;
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 463) }
61a707c543e2a (Christoph Hellwig 2020-05-08 08:54:16 +0200 464)
bdd1d2d3d251c (Christoph Hellwig 2017-09-01 17:39:13 +0200 465) ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
c41fbad015dab (Christoph Hellwig 2017-09-01 17:39:12 +0200 466) {
6209dd9132e8e (Christoph Hellwig 2020-05-08 09:00:28 +0200 467) ssize_t ret;
c41fbad015dab (Christoph Hellwig 2017-09-01 17:39:12 +0200 468)
6209dd9132e8e (Christoph Hellwig 2020-05-08 09:00:28 +0200 469) ret = rw_verify_area(READ, file, pos, count);
6209dd9132e8e (Christoph Hellwig 2020-05-08 09:00:28 +0200 470) if (ret)
6209dd9132e8e (Christoph Hellwig 2020-05-08 09:00:28 +0200 471) return ret;
6209dd9132e8e (Christoph Hellwig 2020-05-08 09:00:28 +0200 472) return __kernel_read(file, buf, count, pos);
c41fbad015dab (Christoph Hellwig 2017-09-01 17:39:12 +0200 473) }
c41fbad015dab (Christoph Hellwig 2017-09-01 17:39:12 +0200 474) EXPORT_SYMBOL(kernel_read);
6fb5032ebb1c5 (Dmitry Kasatkin 2014-11-05 17:01:17 +0200 475)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 476) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 477) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 480) if (!(file->f_mode & FMODE_READ))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 481) return -EBADF;
7f7f25e82d548 (Al Viro 2014-02-11 17:49:24 -0500 482) if (!(file->f_mode & FMODE_CAN_READ))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483) return -EINVAL;
96d4f267e40f9 (Linus Torvalds 2019-01-03 18:57:57 -0800 484) if (unlikely(!access_ok(buf, count)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 485) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 486)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 487) ret = rw_verify_area(READ, file, pos, count);
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 488) if (ret)
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 489) return ret;
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 490) if (count > MAX_RW_COUNT)
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 491) count = MAX_RW_COUNT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 492)
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 493) if (file->f_op->read)
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 494) ret = file->f_op->read(file, buf, count, pos);
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 495) else if (file->f_op->read_iter)
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 496) ret = new_sync_read(file, buf, count, pos);
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 497) else
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 498) ret = -EINVAL;
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 499) if (ret > 0) {
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 500) fsnotify_access(file);
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 501) add_rchar(current, ret);
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 502) }
775802c0571fb (Christoph Hellwig 2020-05-08 11:17:46 +0200 503) inc_syscr(current);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 504) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 505) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 506)
5d5d568975307 (Al Viro 2015-04-03 15:41:18 -0400 507) static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 508) {
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 509) struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 510) struct kiocb kiocb;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 511) struct iov_iter iter;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 512) ssize_t ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 513)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 514) init_sync_kiocb(&kiocb, filp);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 515) kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 516) iov_iter_init(&iter, WRITE, &iov, 1, len);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 517)
bb7462b6fd64e (Miklos Szeredi 2017-02-20 16:51:23 +0100 518) ret = call_write_iter(filp, &kiocb, &iter);
599bd19bdc4c6 (Christoph Hellwig 2015-02-11 19:59:44 +0100 519) BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 520) if (ret > 0 && ppos)
f765b134c0d3f (Al Viro 2015-04-06 20:50:38 -0400 521) *ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 522) return ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 523) }
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 524)
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 525) /* caller is responsible for file_start_write/file_end_write */
73e18f7c0b3e1 (Christoph Hellwig 2017-09-01 17:39:15 +0200 526) ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 527) {
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 528) struct kvec iov = {
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 529) .iov_base = (void *)buf,
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 530) .iov_len = min_t(size_t, count, MAX_RW_COUNT),
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 531) };
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 532) struct kiocb kiocb;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 533) struct iov_iter iter;
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 534) ssize_t ret;
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 535)
a01ac27be4729 (Christoph Hellwig 2020-05-08 08:55:03 +0200 536) if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
a01ac27be4729 (Christoph Hellwig 2020-05-08 08:55:03 +0200 537) return -EBADF;
7f7f25e82d548 (Al Viro 2014-02-11 17:49:24 -0500 538) if (!(file->f_mode & FMODE_CAN_WRITE))
3e84f48edfd33 (Al Viro 2013-03-27 15:20:30 +0000 539) return -EINVAL;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 540) /*
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 541) * Also fail if ->write_iter and ->write are both wired up as that
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 542) * implies very convoluted semantics.
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 543) */
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 544) if (unlikely(!file->f_op->write_iter || file->f_op->write))
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 545) return warn_unsupported(file, "write");
3e84f48edfd33 (Al Viro 2013-03-27 15:20:30 +0000 546)
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 547) init_sync_kiocb(&kiocb, file);
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100 548) kiocb.ki_pos = pos ? *pos : 0;
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 549) iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
4d03e3cc59828 (Christoph Hellwig 2020-09-03 16:22:33 +0200 550) ret = file->f_op->write_iter(&kiocb, &iter);
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 551) if (ret > 0) {
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100 552) if (pos)
4c207ef482693 (Matthew Wilcox (Oracle) 2020-10-03 03:55:22 +0100 553) *pos = kiocb.ki_pos;
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 554) fsnotify_modify(file);
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 555) add_wchar(current, ret);
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 556) }
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 557) inc_syscw(current);
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 558) return ret;
06ae43f34bcc0 (Al Viro 2013-03-20 13:19:30 -0400 559) }
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 560) /*
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 561) * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 562) * but autofs is one of the few internal kernel users that actually
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 563) * wants this _and_ can be built as a module. So we need to export
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 564) * this symbol for autofs, even though it really isn't appropriate
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 565) * for any other kernel modules.
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 566) */
90fb702791bf9 (Linus Torvalds 2020-09-29 17:18:34 -0700 567) EXPORT_SYMBOL_GPL(__kernel_write);
2ec3a12a66784 (Al Viro 2014-08-19 11:48:09 -0400 568)
e13ec939e96b1 (Christoph Hellwig 2017-09-01 17:39:14 +0200 569) ssize_t kernel_write(struct file *file, const void *buf, size_t count,
e13ec939e96b1 (Christoph Hellwig 2017-09-01 17:39:14 +0200 570) loff_t *pos)
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 571) {
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 572) ssize_t ret;
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 573)
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 574) ret = rw_verify_area(WRITE, file, pos, count);
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 575) if (ret)
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 576) return ret;
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 577)
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 578) file_start_write(file);
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 579) ret = __kernel_write(file, buf, count, pos);
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 580) file_end_write(file);
81238b2cff146 (Christoph Hellwig 2020-05-07 19:33:03 +0200 581) return ret;
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 582) }
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 583) EXPORT_SYMBOL(kernel_write);
ac452acae1caa (Christoph Hellwig 2017-09-01 17:39:11 +0200 584)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 585) ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 586) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 588)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 589) if (!(file->f_mode & FMODE_WRITE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 590) return -EBADF;
7f7f25e82d548 (Al Viro 2014-02-11 17:49:24 -0500 591) if (!(file->f_mode & FMODE_CAN_WRITE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 592) return -EINVAL;
96d4f267e40f9 (Linus Torvalds 2019-01-03 18:57:57 -0800 593) if (unlikely(!access_ok(buf, count)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 594) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 595)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 596) ret = rw_verify_area(WRITE, file, pos, count);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 597) if (ret)
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 598) return ret;
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 599) if (count > MAX_RW_COUNT)
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 600) count = MAX_RW_COUNT;
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 601) file_start_write(file);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 602) if (file->f_op->write)
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 603) ret = file->f_op->write(file, buf, count, pos);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 604) else if (file->f_op->write_iter)
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 605) ret = new_sync_write(file, buf, count, pos);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 606) else
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 607) ret = -EINVAL;
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 608) if (ret > 0) {
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 609) fsnotify_modify(file);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 610) add_wchar(current, ret);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 611) }
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 612) inc_syscw(current);
53ad86266bda9 (Christoph Hellwig 2020-05-13 08:51:46 +0200 613) file_end_write(file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 614) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 615) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 616)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 617) /* file_ppos returns &file->f_pos or NULL if file is stream */
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 618) static inline loff_t *file_ppos(struct file *file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 620) return file->f_mode & FMODE_STREAM ? NULL : &file->f_pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 621) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622)
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 623) ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 624) {
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 625) struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 627)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 628) if (f.file) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 629) loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 630) if (ppos) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 631) pos = *ppos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 632) ppos = &pos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 633) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 634) ret = vfs_read(f.file, buf, count, ppos);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 635) if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 636) f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 637) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 638) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 639) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 641)
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 642) SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 643) {
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 644) return ksys_read(fd, buf, count);
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 645) }
3ce4a7bf66263 (Dominik Brodowski 2018-03-13 21:56:26 +0100 646)
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 647) ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 648) {
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 649) struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 650) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 651)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 652) if (f.file) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 653) loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 654) if (ppos) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 655) pos = *ppos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 656) ppos = &pos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 657) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 658) ret = vfs_write(f.file, buf, count, ppos);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 659) if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 660) f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 661) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 662) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 663)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 664) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 665) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 666)
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 667) SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 668) size_t, count)
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 669) {
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 670) return ksys_write(fd, buf, count);
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 671) }
e7a3e8b2edf54 (Dominik Brodowski 2018-03-11 11:34:41 +0100 672)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 673) ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 674) loff_t pos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 675) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 676) struct fd f;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 677) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 678)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 679) if (pos < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 680) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 681)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 682) f = fdget(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 683) if (f.file) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 684) ret = -ESPIPE;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 685) if (f.file->f_mode & FMODE_PREAD)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 686) ret = vfs_read(f.file, buf, count, &pos);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 687) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 688) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 689)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 690) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 691) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 692)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 693) SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 694) size_t, count, loff_t, pos)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 695) {
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 696) return ksys_pread64(fd, buf, count, pos);
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 697) }
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 698)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 699) ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 700) size_t count, loff_t pos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 701) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 702) struct fd f;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 703) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 704)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 705) if (pos < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 706) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 707)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 708) f = fdget(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 709) if (f.file) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 710) ret = -ESPIPE;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 711) if (f.file->f_mode & FMODE_PWRITE)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 712) ret = vfs_write(f.file, buf, count, &pos);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 713) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 714) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 715)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 716) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 717) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 719) SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 720) size_t, count, loff_t, pos)
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 721) {
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 722) return ksys_pwrite64(fd, buf, count, pos);
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 723) }
36028d5dd7117 (Dominik Brodowski 2018-03-19 17:38:31 +0100 724)
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 725) static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 726) loff_t *ppos, int type, rwf_t flags)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 727) {
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 728) struct kiocb kiocb;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 729) ssize_t ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 730)
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 731) init_sync_kiocb(&kiocb, filp);
fdd2f5b7de2af (Goldwyn Rodrigues 2017-06-20 07:05:40 -0500 732) ret = kiocb_set_rw_flags(&kiocb, flags);
fdd2f5b7de2af (Goldwyn Rodrigues 2017-06-20 07:05:40 -0500 733) if (ret)
fdd2f5b7de2af (Goldwyn Rodrigues 2017-06-20 07:05:40 -0500 734) return ret;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 735) kiocb.ki_pos = (ppos ? *ppos : 0);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 736)
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 737) if (type == READ)
bb7462b6fd64e (Miklos Szeredi 2017-02-20 16:51:23 +0100 738) ret = call_read_iter(filp, &kiocb, iter);
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 739) else
bb7462b6fd64e (Miklos Szeredi 2017-02-20 16:51:23 +0100 740) ret = call_write_iter(filp, &kiocb, iter);
599bd19bdc4c6 (Christoph Hellwig 2015-02-11 19:59:44 +0100 741) BUG_ON(ret == -EIOCBQUEUED);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 742) if (ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 743) *ppos = kiocb.ki_pos;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 744) return ret;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 745) }
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 746)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 747) /* Do it by hand, with file-ops */
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 748) static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 749) loff_t *ppos, int type, rwf_t flags)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 750) {
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 751) ssize_t ret = 0;
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 752)
97be7ebe53915 (Christoph Hellwig 2016-03-03 16:04:01 +0100 753) if (flags & ~RWF_HIPRI)
793b80ef14af5 (Christoph Hellwig 2016-03-03 16:03:58 +0100 754) return -EOPNOTSUPP;
793b80ef14af5 (Christoph Hellwig 2016-03-03 16:03:58 +0100 755)
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 756) while (iov_iter_count(iter)) {
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 757) struct iovec iovec = iov_iter_iovec(iter);
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 758) ssize_t nr;
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 759)
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 760) if (type == READ) {
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 761) nr = filp->f_op->read(filp, iovec.iov_base,
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 762) iovec.iov_len, ppos);
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 763) } else {
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 764) nr = filp->f_op->write(filp, iovec.iov_base,
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 765) iovec.iov_len, ppos);
0f78d06ac1e9b (Miklos Szeredi 2017-02-20 16:51:23 +0100 766) }
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 767)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 768) if (nr < 0) {
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 769) if (!ret)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 770) ret = nr;
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 771) break;
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 772) }
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 773) ret += nr;
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 774) if (nr != iovec.iov_len)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 775) break;
ac15ac0669d5f (Al Viro 2015-03-20 20:10:21 -0400 776) iov_iter_advance(iter, nr);
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 777) }
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 778)
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 779) return ret;
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 780) }
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 781)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 782) static ssize_t do_iter_read(struct file *file, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 783) loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 784) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 785) size_t tot_len;
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 786) ssize_t ret = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 787)
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 788) if (!(file->f_mode & FMODE_READ))
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 789) return -EBADF;
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 790) if (!(file->f_mode & FMODE_CAN_READ))
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 791) return -EINVAL;
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 792)
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 793) tot_len = iov_iter_count(iter);
0504c074b5466 (Al Viro 2015-03-21 19:40:11 -0400 794) if (!tot_len)
0504c074b5466 (Al Viro 2015-03-21 19:40:11 -0400 795) goto out;
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 796) ret = rw_verify_area(READ, file, pos, tot_len);
e28cc71572da3 (Linus Torvalds 2006-01-04 16:20:40 -0800 797) if (ret < 0)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 798) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 799)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 800) if (file->f_op->read_iter)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 801) ret = do_iter_readv_writev(file, iter, pos, READ, flags);
ee0b3e671baff (Badari Pulavarty 2006-09-30 23:28:47 -0700 802) else
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 803) ret = do_loop_readv_writev(file, iter, pos, READ, flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 804) out:
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 805) if (ret >= 0)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 806) fsnotify_access(file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 807) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 808) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 809)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 810) ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 811) struct iov_iter *iter)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 812) {
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 813) size_t tot_len;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 814) ssize_t ret = 0;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 815)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 816) if (!file->f_op->read_iter)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 817) return -EINVAL;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 818) if (!(file->f_mode & FMODE_READ))
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 819) return -EBADF;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 820) if (!(file->f_mode & FMODE_CAN_READ))
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 821) return -EINVAL;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 822)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 823) tot_len = iov_iter_count(iter);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 824) if (!tot_len)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 825) goto out;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 826) ret = rw_verify_area(READ, file, &iocb->ki_pos, tot_len);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 827) if (ret < 0)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 828) return ret;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 829)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 830) ret = call_read_iter(file, iocb, iter);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 831) out:
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 832) if (ret >= 0)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 833) fsnotify_access(file);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 834) return ret;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 835) }
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 836) EXPORT_SYMBOL(vfs_iocb_iter_read);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 837)
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 838) ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 839) rwf_t flags)
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 840) {
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 841) if (!file->f_op->read_iter)
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 842) return -EINVAL;
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 843) return do_iter_read(file, iter, ppos, flags);
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 844) }
18e9710ee59ce (Christoph Hellwig 2017-05-27 11:16:51 +0300 845) EXPORT_SYMBOL(vfs_iter_read);
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 846)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 847) static ssize_t do_iter_write(struct file *file, struct iov_iter *iter,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 848) loff_t *pos, rwf_t flags)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 849) {
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 850) size_t tot_len;
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 851) ssize_t ret = 0;
03d95eb2f2578 (Al Viro 2013-03-20 13:04:20 -0400 852)
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 853) if (!(file->f_mode & FMODE_WRITE))
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 854) return -EBADF;
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 855) if (!(file->f_mode & FMODE_CAN_WRITE))
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 856) return -EINVAL;
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 857)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 858) tot_len = iov_iter_count(iter);
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 859) if (!tot_len)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 860) return 0;
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 861) ret = rw_verify_area(WRITE, file, pos, tot_len);
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 862) if (ret < 0)
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 863) return ret;
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 864)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 865) if (file->f_op->write_iter)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 866) ret = do_iter_readv_writev(file, iter, pos, WRITE, flags);
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 867) else
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 868) ret = do_loop_readv_writev(file, iter, pos, WRITE, flags);
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 869) if (ret > 0)
19c735868dd01 (Christoph Hellwig 2017-05-27 11:16:48 +0300 870) fsnotify_modify(file);
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 871) return ret;
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 872) }
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 873)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 874) ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 875) struct iov_iter *iter)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 876) {
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 877) size_t tot_len;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 878) ssize_t ret = 0;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 879)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 880) if (!file->f_op->write_iter)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 881) return -EINVAL;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 882) if (!(file->f_mode & FMODE_WRITE))
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 883) return -EBADF;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 884) if (!(file->f_mode & FMODE_CAN_WRITE))
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 885) return -EINVAL;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 886)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 887) tot_len = iov_iter_count(iter);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 888) if (!tot_len)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 889) return 0;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 890) ret = rw_verify_area(WRITE, file, &iocb->ki_pos, tot_len);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 891) if (ret < 0)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 892) return ret;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 893)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 894) ret = call_write_iter(file, iocb, iter);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 895) if (ret > 0)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 896) fsnotify_modify(file);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 897)
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 898) return ret;
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 899) }
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 900) EXPORT_SYMBOL(vfs_iocb_iter_write);
5dcdc43e24a18 (Jiufei Xue 2019-11-20 17:45:25 +0800 901)
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 902) ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 903) rwf_t flags)
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 904) {
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 905) if (!file->f_op->write_iter)
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 906) return -EINVAL;
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 907) return do_iter_write(file, iter, ppos, flags);
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 908) }
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 909) EXPORT_SYMBOL(vfs_iter_write);
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 910)
36e2c7421f02a (Christoph Hellwig 2020-09-03 16:22:34 +0200 911) static ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 912) unsigned long vlen, loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 913) {
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 914) struct iovec iovstack[UIO_FASTIOV];
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 915) struct iovec *iov = iovstack;
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 916) struct iov_iter iter;
7687a7a4435f4 (Miklos Szeredi 2017-02-20 16:51:23 +0100 917) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 918)
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 919) ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 920) if (ret >= 0) {
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 921) ret = do_iter_read(file, &iter, pos, flags);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 922) kfree(iov);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 923) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 924)
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 925) return ret;
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 926) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 927)
9725d4cef6222 (Christoph Hellwig 2017-09-01 17:39:25 +0200 928) static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 929) unsigned long vlen, loff_t *pos, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 930) {
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 931) struct iovec iovstack[UIO_FASTIOV];
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 932) struct iovec *iov = iovstack;
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 933) struct iov_iter iter;
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 934) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 935)
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 936) ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 937) if (ret >= 0) {
62473a2d6f513 (Al Viro 2017-07-06 09:15:47 -0400 938) file_start_write(file);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 939) ret = do_iter_write(file, &iter, pos, flags);
62473a2d6f513 (Al Viro 2017-07-06 09:15:47 -0400 940) file_end_write(file);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 941) kfree(iov);
edab5fe38c2c1 (Christoph Hellwig 2017-05-27 11:16:49 +0300 942) }
251b42a1dc641 (Christoph Hellwig 2017-05-27 11:16:46 +0300 943) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 944) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 945)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 946) static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 947) unsigned long vlen, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 948) {
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 949) struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 950) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 951)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 952) if (f.file) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 953) loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 954) if (ppos) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 955) pos = *ppos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 956) ppos = &pos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 957) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 958) ret = vfs_readv(f.file, vec, vlen, ppos, flags);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 959) if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 960) f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 961) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 962) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 963)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 964) if (ret > 0)
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 965) add_rchar(current, ret);
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 966) inc_syscr(current);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 967) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 968) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 969)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 970) static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 971) unsigned long vlen, rwf_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 972) {
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 973) struct fd f = fdget_pos(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 974) ssize_t ret = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 975)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 976) if (f.file) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 977) loff_t pos, *ppos = file_ppos(f.file);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 978) if (ppos) {
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 979) pos = *ppos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 980) ppos = &pos;
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 981) }
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 982) ret = vfs_writev(f.file, vec, vlen, ppos, flags);
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 983) if (ret >= 0 && ppos)
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 984) f.file->f_pos = pos;
9c225f2655e36 (Linus Torvalds 2014-03-03 09:36:58 -0800 985) fdput_pos(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 986) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 987)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 988) if (ret > 0)
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 989) add_wchar(current, ret);
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 990) inc_syscw(current);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 991) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 992) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 993)
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 994) static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 995) {
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 996) #define HALF_LONG_BITS (BITS_PER_LONG / 2)
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 997) return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 998) }
601cc11d054ae (Linus Torvalds 2009-04-03 08:03:22 -0700 999)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1000) static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1001) unsigned long vlen, loff_t pos, rwf_t flags)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1002) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1003) struct fd f;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1004) ssize_t ret = -EBADF;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1005)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1006) if (pos < 0)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1007) return -EINVAL;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1008)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1009) f = fdget(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1010) if (f.file) {
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1011) ret = -ESPIPE;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1012) if (f.file->f_mode & FMODE_PREAD)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1013) ret = vfs_readv(f.file, vec, vlen, &pos, flags);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1014) fdput(f);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1015) }
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1016)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1017) if (ret > 0)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1018) add_rchar(current, ret);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1019) inc_syscr(current);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1020) return ret;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1021) }
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1022)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1023) static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1024) unsigned long vlen, loff_t pos, rwf_t flags)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1025) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1026) struct fd f;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1027) ssize_t ret = -EBADF;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1028)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1029) if (pos < 0)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1030) return -EINVAL;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1031)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1032) f = fdget(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1033) if (f.file) {
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1034) ret = -ESPIPE;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1035) if (f.file->f_mode & FMODE_PWRITE)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1036) ret = vfs_writev(f.file, vec, vlen, &pos, flags);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1037) fdput(f);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1038) }
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1039)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1040) if (ret > 0)
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1041) add_wchar(current, ret);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1042) inc_syscw(current);
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1043) return ret;
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1044) }
f3554f4bc6980 (Gerd Hoffmann 2009-04-02 16:59:23 -0700 1045)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1046) SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1047) unsigned long, vlen)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1048) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1049) return do_readv(fd, vec, vlen, 0);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1050) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1051)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1052) SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1053) unsigned long, vlen)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1054) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1055) return do_writev(fd, vec, vlen, 0);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1056) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1057)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1058) SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1059) unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1060) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1061) loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1062)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1063) return do_preadv(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1064) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1065)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1066) SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1067) unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1068) rwf_t, flags)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1069) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1070) loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1071)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1072) if (pos == -1)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1073) return do_readv(fd, vec, vlen, flags);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1074)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1075) return do_preadv(fd, vec, vlen, pos, flags);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1076) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1077)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1078) SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1079) unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1080) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1081) loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1082)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1083) return do_pwritev(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1084) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1085)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1086) SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1087) unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1088) rwf_t, flags)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1089) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1090) loff_t pos = pos_from_hilo(pos_h, pos_l);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1091)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1092) if (pos == -1)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1093) return do_writev(fd, vec, vlen, flags);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1094)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1095) return do_pwritev(fd, vec, vlen, pos, flags);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1096) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1097)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1098) /*
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1099) * Various compat syscalls. Note that they all pretend to take a native
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1100) * iovec - import_iovec will properly treat those as compat_iovecs based on
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1101) * in_compat_syscall().
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1102) */
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1103) #ifdef CONFIG_COMPAT
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1104) #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1105) COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1106) const struct iovec __user *, vec,
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1107) unsigned long, vlen, loff_t, pos)
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1108) {
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1109) return do_preadv(fd, vec, vlen, pos, 0);
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1110) }
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1111) #endif
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1112)
dfd948e32af2e (Heiko Carstens 2014-01-29 14:05:44 -0800 1113) COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1114) const struct iovec __user *, vec,
dfd948e32af2e (Heiko Carstens 2014-01-29 14:05:44 -0800 1115) compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1116) {
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1117) loff_t pos = ((loff_t)pos_high << 32) | pos_low;
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1118)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1119) return do_preadv(fd, vec, vlen, pos, 0);
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1120) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1121)
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1122) #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64V2
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1123) COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1124) const struct iovec __user *, vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1125) unsigned long, vlen, loff_t, pos, rwf_t, flags)
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1126) {
cc4b1242d7e3b (Aurelien Jarno 2018-12-06 20:05:34 +0100 1127) if (pos == -1)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1128) return do_readv(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1129) return do_preadv(fd, vec, vlen, pos, flags);
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1130) }
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1131) #endif
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1132)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1133) COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1134) const struct iovec __user *, vec,
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1135) compat_ulong_t, vlen, u32, pos_low, u32, pos_high,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1136) rwf_t, flags)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1137) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1138) loff_t pos = ((loff_t)pos_high << 32) | pos_low;
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1139)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1140) if (pos == -1)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1141) return do_readv(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1142) return do_preadv(fd, vec, vlen, pos, flags);
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1143) }
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1144)
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1145) #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1146) COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1147) const struct iovec __user *, vec,
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1148) unsigned long, vlen, loff_t, pos)
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1149) {
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1150) return do_pwritev(fd, vec, vlen, pos, 0);
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1151) }
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1152) #endif
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1153)
dfd948e32af2e (Heiko Carstens 2014-01-29 14:05:44 -0800 1154) COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1155) const struct iovec __user *,vec,
dfd948e32af2e (Heiko Carstens 2014-01-29 14:05:44 -0800 1156) compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1157) {
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1158) loff_t pos = ((loff_t)pos_high << 32) | pos_low;
378a10f3ae2e8 (Heiko Carstens 2014-03-05 10:43:51 +0100 1159)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1160) return do_pwritev(fd, vec, vlen, pos, 0);
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1161) }
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1162)
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1163) #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64V2
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1164) COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1165) const struct iovec __user *, vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1166) unsigned long, vlen, loff_t, pos, rwf_t, flags)
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1167) {
cc4b1242d7e3b (Aurelien Jarno 2018-12-06 20:05:34 +0100 1168) if (pos == -1)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1169) return do_writev(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1170) return do_pwritev(fd, vec, vlen, pos, flags);
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1171) }
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1172) #endif
3ebfd81f7fb3e (H.J. Lu 2016-07-14 12:31:53 -0700 1173)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1174) COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1175) const struct iovec __user *,vec,
ddef7ed2b5cba (Christoph Hellwig 2017-07-06 18:58:37 +0200 1176) compat_ulong_t, vlen, u32, pos_low, u32, pos_high, rwf_t, flags)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1177) {
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1178) loff_t pos = ((loff_t)pos_high << 32) | pos_low;
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1179)
f17d8b35452ca (Milosz Tanski 2016-03-03 16:03:59 +0100 1180) if (pos == -1)
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1181) return do_writev(fd, vec, vlen, flags);
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1182) return do_pwritev(fd, vec, vlen, pos, flags);
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1183) }
3523a9d454789 (Christoph Hellwig 2020-09-25 06:51:42 +0200 1184) #endif /* CONFIG_COMPAT */
72ec35163f9f7 (Al Viro 2013-03-20 10:42:10 -0400 1185)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1186) static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1187) size_t count, loff_t max)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1188) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1189) struct fd in, out;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1190) struct inode *in_inode, *out_inode;
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1191) struct pipe_inode_info *opipe;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1192) loff_t pos;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1193) loff_t out_pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1194) ssize_t retval;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1195) int fl;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1196)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1197) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1198) * Get input file, and verify that it is ok..
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1199) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1200) retval = -EBADF;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1201) in = fdget(in_fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1202) if (!in.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1203) goto out;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1204) if (!(in.file->f_mode & FMODE_READ))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1205) goto fput_in;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1206) retval = -ESPIPE;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1207) if (!ppos) {
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1208) pos = in.file->f_pos;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1209) } else {
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1210) pos = *ppos;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1211) if (!(in.file->f_mode & FMODE_PREAD))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1212) goto fput_in;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1213) }
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1214) retval = rw_verify_area(READ, in.file, &pos, count);
e28cc71572da3 (Linus Torvalds 2006-01-04 16:20:40 -0800 1215) if (retval < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1216) goto fput_in;
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1217) if (count > MAX_RW_COUNT)
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1218) count = MAX_RW_COUNT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1219)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1220) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1221) * Get output file, and verify that it is ok..
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1222) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1223) retval = -EBADF;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1224) out = fdget(out_fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1225) if (!out.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1226) goto fput_in;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1227) if (!(out.file->f_mode & FMODE_WRITE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1228) goto fput_out;
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 1229) in_inode = file_inode(in.file);
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 1230) out_inode = file_inode(out.file);
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1231) out_pos = out.file->f_pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1232)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1233) if (!max)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1234) max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1235)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1236) if (unlikely(pos + count > max)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1237) retval = -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1238) if (pos >= max)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1239) goto fput_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1240) count = max - pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1241) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1242)
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1243) fl = 0;
534f2aaa6ab07 (Jens Axboe 2007-06-01 14:52:37 +0200 1244) #if 0
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1245) /*
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1246) * We need to debate whether we can enable this or not. The
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1247) * man page documents EAGAIN return for the output at least,
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1248) * and the application is arguably buggy if it doesn't expect
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1249) * EAGAIN on a non-blocking file descriptor.
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1250) */
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1251) if (in.file->f_flags & O_NONBLOCK)
d96e6e7164784 (Jens Axboe 2007-06-11 12:18:52 +0200 1252) fl = SPLICE_F_NONBLOCK;
534f2aaa6ab07 (Jens Axboe 2007-06-01 14:52:37 +0200 1253) #endif
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1254) opipe = get_pipe_info(out.file, true);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1255) if (!opipe) {
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1256) retval = rw_verify_area(WRITE, out.file, &out_pos, count);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1257) if (retval < 0)
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1258) goto fput_out;
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1259) file_start_write(out.file);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1260) retval = do_splice_direct(in.file, &pos, out.file, &out_pos,
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1261) count, fl);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1262) file_end_write(out.file);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1263) } else {
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1264) retval = splice_file_to_pipe(in.file, opipe, &pos, count, fl);
b964bf53e5402 (Al Viro 2021-01-25 22:24:28 -0500 1265) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1266)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1267) if (retval > 0) {
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 1268) add_rchar(current, retval);
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 1269) add_wchar(current, retval);
a68c2f12b4b28 (Scott Wolchok 2012-12-20 15:05:52 -0800 1270) fsnotify_access(in.file);
a68c2f12b4b28 (Scott Wolchok 2012-12-20 15:05:52 -0800 1271) fsnotify_modify(out.file);
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1272) out.file->f_pos = out_pos;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1273) if (ppos)
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1274) *ppos = pos;
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1275) else
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1276) in.file->f_pos = pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1277) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1278)
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 1279) inc_syscr(current);
4b98d11b40f03 (Alexey Dobriyan 2007-02-10 01:46:45 -0800 1280) inc_syscw(current);
7995bd287134f (Al Viro 2013-06-20 18:58:36 +0400 1281) if (pos > max)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1282) retval = -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1283)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1284) fput_out:
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1285) fdput(out);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1286) fput_in:
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 1287) fdput(in);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1288) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1289) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1290) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1291)
002c8976ee537 (Heiko Carstens 2009-01-14 14:14:18 +0100 1292) SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd, off_t __user *, offset, size_t, count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1293) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1294) loff_t pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1295) off_t off;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1296) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1297)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1298) if (offset) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1299) if (unlikely(get_user(off, offset)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1300) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1301) pos = off;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1302) ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1303) if (unlikely(put_user(pos, offset)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1304) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1305) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1306) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1307)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1308) return do_sendfile(out_fd, in_fd, NULL, count, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1309) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1310)
002c8976ee537 (Heiko Carstens 2009-01-14 14:14:18 +0100 1311) SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1312) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1313) loff_t pos;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1314) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1315)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1316) if (offset) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1317) if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1318) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1319) ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1320) if (unlikely(put_user(pos, offset)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1321) return -EFAULT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1322) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1323) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1324)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1325) return do_sendfile(out_fd, in_fd, NULL, count, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1326) }
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1327)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1328) #ifdef CONFIG_COMPAT
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1329) COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1330) compat_off_t __user *, offset, compat_size_t, count)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1331) {
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1332) loff_t pos;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1333) off_t off;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1334) ssize_t ret;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1335)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1336) if (offset) {
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1337) if (unlikely(get_user(off, offset)))
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1338) return -EFAULT;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1339) pos = off;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1340) ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1341) if (unlikely(put_user(pos, offset)))
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1342) return -EFAULT;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1343) return ret;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1344) }
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1345)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1346) return do_sendfile(out_fd, in_fd, NULL, count, 0);
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1347) }
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1348)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1349) COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1350) compat_loff_t __user *, offset, compat_size_t, count)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1351) {
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1352) loff_t pos;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1353) ssize_t ret;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1354)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1355) if (offset) {
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1356) if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1357) return -EFAULT;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1358) ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1359) if (unlikely(put_user(pos, offset)))
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1360) return -EFAULT;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1361) return ret;
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1362) }
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1363)
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1364) return do_sendfile(out_fd, in_fd, NULL, count, 0);
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1365) }
19f4fc3aee180 (Al Viro 2013-02-24 02:17:03 -0500 1366) #endif
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1367)
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1368) /**
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1369) * generic_copy_file_range - copy data between two files
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1370) * @file_in: file structure to read from
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1371) * @pos_in: file offset to read from
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1372) * @file_out: file structure to write data to
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1373) * @pos_out: file offset to write data to
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1374) * @len: amount of data to copy
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1375) * @flags: copy flags
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1376) *
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1377) * This is a generic filesystem helper to copy data from one file to another.
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1378) * It has no constraints on the source or destination file owners - the files
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1379) * can belong to different superblocks and different filesystem types. Short
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1380) * copies are allowed.
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1381) *
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1382) * This should be called from the @file_out filesystem, as per the
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1383) * ->copy_file_range() method.
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1384) *
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1385) * Returns the number of bytes copied or a negative error indicating the
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1386) * failure.
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1387) */
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1388)
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1389) ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1390) struct file *file_out, loff_t pos_out,
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1391) size_t len, unsigned int flags)
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1392) {
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1393) return do_splice_direct(file_in, &pos_in, file_out, &pos_out,
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1394) len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1395) }
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1396) EXPORT_SYMBOL(generic_copy_file_range);
f16acc9d9b376 (Dave Chinner 2019-06-05 08:04:47 -0700 1397)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1398) static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1399) struct file *file_out, loff_t pos_out,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1400) size_t len, unsigned int flags)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1401) {
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1402) /*
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1403) * Although we now allow filesystems to handle cross sb copy, passing
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1404) * a file of the wrong filesystem type to filesystem driver can result
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1405) * in an attempt to dereference the wrong type of ->private_data, so
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1406) * avoid doing that until we really have a good reason. NFS defines
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1407) * several different file_system_type structures, but they all end up
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1408) * using the same ->copy_file_range() function pointer.
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1409) */
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1410) if (file_out->f_op->copy_file_range &&
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1411) file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1412) return file_out->f_op->copy_file_range(file_in, pos_in,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1413) file_out, pos_out,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1414) len, flags);
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1415)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1416) return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1417) flags);
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1418) }
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1419)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1420) /*
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1421) * Performs necessary checks before doing a file copy
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1422) *
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1423) * Can adjust amount of bytes to copy via @req_count argument.
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1424) * Returns appropriate error code that caller should return or
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1425) * zero in case the copy should be allowed.
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1426) */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1427) static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1428) struct file *file_out, loff_t pos_out,
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1429) size_t *req_count, unsigned int flags)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1430) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1431) struct inode *inode_in = file_inode(file_in);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1432) struct inode *inode_out = file_inode(file_out);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1433) uint64_t count = *req_count;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1434) loff_t size_in;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1435) int ret;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1436)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1437) ret = generic_file_rw_checks(file_in, file_out);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1438) if (ret)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1439) return ret;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1440)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1441) /* Don't touch certain kinds of inodes */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1442) if (IS_IMMUTABLE(inode_out))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1443) return -EPERM;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1444)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1445) if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1446) return -ETXTBSY;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1447)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1448) /* Ensure offsets don't wrap. */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1449) if (pos_in + count < pos_in || pos_out + count < pos_out)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1450) return -EOVERFLOW;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1451)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1452) /* Shorten the copy to EOF */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1453) size_in = i_size_read(inode_in);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1454) if (pos_in >= size_in)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1455) count = 0;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1456) else
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1457) count = min(count, size_in - (uint64_t)pos_in);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1458)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1459) ret = generic_write_check_limits(file_out, pos_out, &count);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1460) if (ret)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1461) return ret;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1462)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1463) /* Don't allow overlapped copying within the same file. */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1464) if (inode_in == inode_out &&
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1465) pos_out + count > pos_in &&
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1466) pos_out < pos_in + count)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1467) return -EINVAL;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1468)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1469) *req_count = count;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1470) return 0;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1471) }
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1472)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1473) /*
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1474) * copy_file_range() differs from regular file read and write in that it
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1475) * specifically allows return partial success. When it does so is up to
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1476) * the copy_file_range method.
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1477) */
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1478) ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1479) struct file *file_out, loff_t pos_out,
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1480) size_t len, unsigned int flags)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1481) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1482) ssize_t ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1483)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1484) if (flags != 0)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1485) return -EINVAL;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1486)
96e6e8f4a68df (Amir Goldstein 2019-06-05 08:04:49 -0700 1487) ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len,
96e6e8f4a68df (Amir Goldstein 2019-06-05 08:04:49 -0700 1488) flags);
a31713517dac0 (Amir Goldstein 2019-06-05 08:04:48 -0700 1489) if (unlikely(ret))
a31713517dac0 (Amir Goldstein 2019-06-05 08:04:48 -0700 1490) return ret;
11cbfb10775aa (Amir Goldstein 2017-01-31 10:34:56 +0200 1491)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1492) ret = rw_verify_area(READ, file_in, &pos_in, len);
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1493) if (unlikely(ret))
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1494) return ret;
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1495)
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1496) ret = rw_verify_area(WRITE, file_out, &pos_out, len);
bc61384dcdd82 (Al Viro 2016-03-31 21:48:20 -0400 1497) if (unlikely(ret))
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1498) return ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1499)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1500) if (len == 0)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1501) return 0;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1502)
bfe219d373cad (Amir Goldstein 2017-01-31 10:34:57 +0200 1503) file_start_write(file_out);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1504)
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1505) /*
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1506) * Try cloning first, this is supported by more file systems, and
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1507) * more efficient if both clone and copy are supported (e.g. NFS).
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1508) */
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1509) if (file_in->f_op->remap_file_range &&
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 1510) file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1511) loff_t cloned;
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1512)
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1513) cloned = file_in->f_op->remap_file_range(file_in, pos_in,
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1514) file_out, pos_out,
eca3654e3cc7d (Darrick J. Wong 2018-10-30 10:42:10 +1100 1515) min_t(loff_t, MAX_RW_COUNT, len),
eca3654e3cc7d (Darrick J. Wong 2018-10-30 10:42:10 +1100 1516) REMAP_FILE_CAN_SHORTEN);
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1517) if (cloned > 0) {
42ec3d4c02187 (Darrick J. Wong 2018-10-30 10:41:49 +1100 1518) ret = cloned;
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1519) goto done;
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1520) }
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1521) }
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1522)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1523) ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1524) flags);
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 1525) WARN_ON_ONCE(ret == -EOPNOTSUPP);
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1526) done:
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1527) if (ret > 0) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1528) fsnotify_access(file_in);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1529) add_rchar(current, ret);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1530) fsnotify_modify(file_out);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1531) add_wchar(current, ret);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1532) }
a76b5b04375f9 (Christoph Hellwig 2016-12-09 16:17:19 -0800 1533)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1534) inc_syscr(current);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1535) inc_syscw(current);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1536)
bfe219d373cad (Amir Goldstein 2017-01-31 10:34:57 +0200 1537) file_end_write(file_out);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1538)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1539) return ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1540) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1541) EXPORT_SYMBOL(vfs_copy_file_range);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1542)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1543) SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1544) int, fd_out, loff_t __user *, off_out,
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1545) size_t, len, unsigned int, flags)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1546) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1547) loff_t pos_in;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1548) loff_t pos_out;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1549) struct fd f_in;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1550) struct fd f_out;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1551) ssize_t ret = -EBADF;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1552)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1553) f_in = fdget(fd_in);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1554) if (!f_in.file)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1555) goto out2;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1556)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1557) f_out = fdget(fd_out);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1558) if (!f_out.file)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1559) goto out1;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1560)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1561) ret = -EFAULT;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1562) if (off_in) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1563) if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1564) goto out;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1565) } else {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1566) pos_in = f_in.file->f_pos;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1567) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1568)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1569) if (off_out) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1570) if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1571) goto out;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1572) } else {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1573) pos_out = f_out.file->f_pos;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1574) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1575)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1576) ret = vfs_copy_file_range(f_in.file, pos_in, f_out.file, pos_out, len,
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1577) flags);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1578) if (ret > 0) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1579) pos_in += ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1580) pos_out += ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1581)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1582) if (off_in) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1583) if (copy_to_user(off_in, &pos_in, sizeof(loff_t)))
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1584) ret = -EFAULT;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1585) } else {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1586) f_in.file->f_pos = pos_in;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1587) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1588)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1589) if (off_out) {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1590) if (copy_to_user(off_out, &pos_out, sizeof(loff_t)))
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1591) ret = -EFAULT;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1592) } else {
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1593) f_out.file->f_pos = pos_out;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1594) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1595) }
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1596)
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1597) out:
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1598) fdput(f_out);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1599) out1:
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1600) fdput(f_in);
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1601) out2:
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1602) return ret;
29732938a6289 (Zach Brown 2015-11-10 16:53:30 -0500 1603) }
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1604)
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1605) /*
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1606) * Don't operate on ranges the page cache doesn't support, and don't exceed the
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1607) * LFS limits. If pos is under the limit it becomes a short access. If it
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1608) * exceeds the limit we return -EFBIG.
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1609) */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1610) int generic_write_check_limits(struct file *file, loff_t pos, loff_t *count)
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1611) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1612) struct inode *inode = file->f_mapping->host;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1613) loff_t max_size = inode->i_sb->s_maxbytes;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1614) loff_t limit = rlimit(RLIMIT_FSIZE);
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1615)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1616) if (limit != RLIM_INFINITY) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1617) if (pos >= limit) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1618) send_sig(SIGXFSZ, current, 0);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1619) return -EFBIG;
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1620) }
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1621) *count = min(*count, limit - pos);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1622) }
edc58dd0123b5 (Darrick J. Wong 2019-08-11 15:52:25 -0700 1623)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1624) if (!(file->f_flags & O_LARGEFILE))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1625) max_size = MAX_NON_LFS;
c32e5f39953fa (Darrick J. Wong 2018-10-30 10:42:17 +1100 1626)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1627) if (unlikely(pos >= max_size))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1628) return -EFBIG;
c32e5f39953fa (Darrick J. Wong 2018-10-30 10:42:17 +1100 1629)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1630) *count = min(*count, max_size - pos);
c32e5f39953fa (Darrick J. Wong 2018-10-30 10:42:17 +1100 1631)
c32e5f39953fa (Darrick J. Wong 2018-10-30 10:42:17 +1100 1632) return 0;
c32e5f39953fa (Darrick J. Wong 2018-10-30 10:42:17 +1100 1633) }
04b38d601239b (Christoph Hellwig 2015-12-03 12:59:50 +0100 1634)
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1635) /*
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1636) * Performs necessary checks before doing a write
22725ce4e4a00 (Darrick J. Wong 2016-12-19 15:13:26 -0800 1637) *
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1638) * Can adjust writing position or amount of bytes to write.
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1639) * Returns appropriate error code that caller should return or
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1640) * zero in case that write should be allowed.
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1641) */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1642) ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1643) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1644) struct file *file = iocb->ki_filp;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1645) struct inode *inode = file->f_mapping->host;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1646) loff_t count;
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1647) int ret;
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1648)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1649) if (IS_SWAPFILE(inode))
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1650) return -ETXTBSY;
876bec6f9bbfc (Darrick J. Wong 2016-12-09 16:18:30 -0800 1651)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1652) if (!iov_iter_count(from))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1653) return 0;
5de4480ae7f8f (Mark Fasheh 2018-09-10 16:21:17 -0700 1654)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1655) /* FIXME: this is for backwards compatibility with 2.4 */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1656) if (iocb->ki_flags & IOCB_APPEND)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1657) iocb->ki_pos = i_size_read(inode);
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1658)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1659) if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1660) return -EINVAL;
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1661)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1662) count = iov_iter_count(from);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1663) ret = generic_write_check_limits(file, iocb->ki_pos, &count);
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1664) if (ret)
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1665) return ret;
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1666)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1667) iov_iter_truncate(from, count);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1668) return iov_iter_count(from);
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1669) }
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1670) EXPORT_SYMBOL(generic_write_checks);
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1671)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1672) /*
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1673) * Performs common checks before doing a file copy/clone
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1674) * from @file_in to @file_out.
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1675) */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1676) int generic_file_rw_checks(struct file *file_in, struct file *file_out)
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1677) {
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1678) struct inode *inode_in = file_inode(file_in);
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1679) struct inode *inode_out = file_inode(file_out);
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1680)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1681) /* Don't copy dirs, pipes, sockets... */
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1682) if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
494633fac7896 (Dave Chinner 2018-11-19 13:31:12 -0800 1683) return -EISDIR;
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1684) if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
22725ce4e4a00 (Darrick J. Wong 2016-12-19 15:13:26 -0800 1685) return -EINVAL;
22725ce4e4a00 (Darrick J. Wong 2016-12-19 15:13:26 -0800 1686)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1687) if (!(file_in->f_mode & FMODE_READ) ||
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1688) !(file_out->f_mode & FMODE_WRITE) ||
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1689) (file_out->f_flags & O_APPEND))
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1690) return -EBADF;
1b4f42a1e33fe (Miklos Szeredi 2018-07-06 23:57:03 +0200 1691)
407e9c63ee571 (Darrick J. Wong 2020-10-15 09:21:17 -0700 1692) return 0;
54dbc15172375 (Darrick J. Wong 2015-12-19 00:55:59 -0800 1693) }