1 /*
2  *  linux/fs/read_write.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  *  Minor pieces Copyright (C) 2002 Red Hat Inc, All Rights Reserved
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 #include <linux/slab.h>
23 #include <linux/stat.h>
24 #include <linux/fcntl.h>
25 #include <linux/file.h>
26 #include <linux/uio.h>
27 #include <linux/smp_lock.h>
28 #include <linux/dnotify.h>
29 
30 #include <asm/uaccess.h>
31 
32 struct file_operations generic_ro_fops = {
33 	llseek:		generic_file_llseek,
34 	read:		generic_file_read,
35 	mmap:		generic_file_mmap,
36 };
37 
generic_read_dir(struct file * filp,char * buf,size_t siz,loff_t * ppos)38 ssize_t generic_read_dir(struct file *filp, char *buf, size_t siz, loff_t *ppos)
39 {
40 	return -EISDIR;
41 }
42 
rw_verify_area(int read_write,struct file * file,loff_t * ppos,size_t count)43 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count)
44 {
45 	struct inode *inode;
46 	loff_t pos;
47 
48 	if (unlikely(count > file->f_maxcount))
49 		goto Einval;
50 
51 	pos = *ppos;
52 
53 	if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
54 		goto Einval;
55 
56 	inode = file->f_dentry->d_inode;
57 	if (inode->i_flock && MANDATORY_LOCK(inode))
58 		return locks_mandatory_area(read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, *ppos, count);
59 	return 0;
60 
61 Einval:
62 	return -EINVAL;
63 }
64 
generic_file_llseek(struct file * file,loff_t offset,int origin)65 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
66 {
67 	long long retval;
68 
69 	switch (origin) {
70 		case 2:
71 			offset += file->f_dentry->d_inode->i_size;
72 			break;
73 		case 1:
74 			offset += file->f_pos;
75 	}
76 	retval = -EINVAL;
77 	if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
78 		if (offset != file->f_pos) {
79 			file->f_pos = offset;
80 			file->f_reada = 0;
81 			file->f_version = ++event;
82 		}
83 		retval = offset;
84 	}
85 	return retval;
86 }
87 
no_llseek(struct file * file,loff_t offset,int origin)88 loff_t no_llseek(struct file *file, loff_t offset, int origin)
89 {
90 	return -ESPIPE;
91 }
92 
default_llseek(struct file * file,loff_t offset,int origin)93 loff_t default_llseek(struct file *file, loff_t offset, int origin)
94 {
95 	long long retval;
96 
97 	switch (origin) {
98 		case 2:
99 			offset += file->f_dentry->d_inode->i_size;
100 			break;
101 		case 1:
102 			offset += file->f_pos;
103 	}
104 	retval = -EINVAL;
105 	if (offset >= 0) {
106 		if (offset != file->f_pos) {
107 			file->f_pos = offset;
108 			file->f_reada = 0;
109 			file->f_version = ++event;
110 		}
111 		retval = offset;
112 	}
113 	return retval;
114 }
115 
llseek(struct file * file,loff_t offset,int origin)116 static inline loff_t llseek(struct file *file, loff_t offset, int origin)
117 {
118 	loff_t (*fn)(struct file *, loff_t, int);
119 	loff_t retval;
120 
121 	fn = default_llseek;
122 	if (file->f_op && file->f_op->llseek)
123 		fn = file->f_op->llseek;
124 	lock_kernel();
125 	retval = fn(file, offset, origin);
126 	unlock_kernel();
127 	return retval;
128 }
129 
sys_lseek(unsigned int fd,off_t offset,unsigned int origin)130 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
131 {
132 	off_t retval;
133 	struct file * file;
134 
135 	retval = -EBADF;
136 	file = fget(fd);
137 	if (!file)
138 		goto bad;
139 	retval = -EINVAL;
140 	if (origin <= 2) {
141 		loff_t res = llseek(file, offset, origin);
142 		retval = res;
143 		if (res != (loff_t)retval)
144 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
145 	}
146 	fput(file);
147 bad:
148 	return retval;
149 }
150 
151 #if !defined(__alpha__)
sys_llseek(unsigned int fd,unsigned long offset_high,unsigned long offset_low,loff_t * result,unsigned int origin)152 asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
153 			   unsigned long offset_low, loff_t * result,
154 			   unsigned int origin)
155 {
156 	int retval;
157 	struct file * file;
158 	loff_t offset;
159 
160 	retval = -EBADF;
161 	file = fget(fd);
162 	if (!file)
163 		goto bad;
164 	retval = -EINVAL;
165 	if (origin > 2)
166 		goto out_putf;
167 
168 	offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
169 			origin);
170 
171 	retval = (int)offset;
172 	if (offset >= 0) {
173 		retval = -EFAULT;
174 		if (!copy_to_user(result, &offset, sizeof(offset)))
175 			retval = 0;
176 	}
177 out_putf:
178 	fput(file);
179 bad:
180 	return retval;
181 }
182 #endif
183 
sys_read(unsigned int fd,char * buf,size_t count)184 asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count)
185 {
186 	ssize_t ret;
187 	struct file * file;
188 
189 	ret = -EBADF;
190 	file = fget(fd);
191 	if (file) {
192 		if (file->f_mode & FMODE_READ) {
193 			ret = rw_verify_area(READ, file, &file->f_pos, count);
194 
195 			if (!ret) {
196 				ssize_t (*read)(struct file *, char *, size_t, loff_t *);
197 				ret = -EINVAL;
198 				if (file->f_op && (read = file->f_op->read) != NULL)
199 					ret = read(file, buf, count, &file->f_pos);
200 			}
201 		}
202 		if (ret > 0)
203 			dnotify_parent(file->f_dentry, DN_ACCESS);
204 		fput(file);
205 	}
206 	return ret;
207 }
208 
sys_write(unsigned int fd,const char * buf,size_t count)209 asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
210 {
211 	ssize_t ret;
212 	struct file * file;
213 
214 	ret = -EBADF;
215 	file = fget(fd);
216 	if (file) {
217 		if (file->f_mode & FMODE_WRITE) {
218 			ret = rw_verify_area(WRITE, file, &file->f_pos, count);
219 			if (!ret) {
220 				ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
221 				ret = -EINVAL;
222 				if (file->f_op && (write = file->f_op->write) != NULL)
223 					ret = write(file, buf, count, &file->f_pos);
224 			}
225 		}
226 		if (ret > 0)
227 			dnotify_parent(file->f_dentry, DN_MODIFY);
228 		fput(file);
229 	}
230 	return ret;
231 }
232 
233 
do_readv_writev(int type,struct file * file,const struct iovec * vector,unsigned long count)234 static ssize_t do_readv_writev(int type, struct file *file,
235 			       const struct iovec * vector,
236 			       unsigned long count)
237 {
238 	typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
239 	typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
240 
241 	size_t tot_len;
242 	struct iovec iovstack[UIO_FASTIOV];
243 	struct iovec *iov=iovstack;
244 	ssize_t ret, i;
245 	io_fn_t fn;
246 	iov_fn_t fnv;
247 
248 	/*
249 	 * First get the "struct iovec" from user memory and
250 	 * verify all the pointers
251 	 */
252 	ret = 0;
253 	if (!count)
254 		goto out_nofree;
255 	ret = -EINVAL;
256 	if (count > UIO_MAXIOV)
257 		goto out_nofree;
258 	if (!file->f_op)
259 		goto out_nofree;
260 	if (count > UIO_FASTIOV) {
261 		ret = -ENOMEM;
262 		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
263 		if (!iov)
264 			goto out_nofree;
265 	}
266 	ret = -EFAULT;
267 	if (copy_from_user(iov, vector, count*sizeof(*vector)))
268 		goto out;
269 
270 	/*
271 	 * Single unix specification:
272 	 * We should -EINVAL if an element length is not >= 0 and fitting an ssize_t
273 	 * The total length is fitting an ssize_t
274 	 *
275 	 * Be careful here because iov_len is a size_t not an ssize_t
276 	 */
277 
278 	tot_len = 0;
279 	ret = -EINVAL;
280 	for (i = 0 ; i < count ; i++) {
281 		ssize_t len = (ssize_t) iov[i].iov_len;
282 		if (len < 0)	/* size_t not fitting an ssize_t .. */
283 			goto out;
284 		tot_len += len;
285 		/* We must do this work unsigned - signed overflow is
286 		   undefined and gcc 3.2 now uses that fact sometimes...
287 
288 		   FIXME: put in a proper limits.h for each platform */
289 #if BITS_PER_LONG==64
290 		if (tot_len > 0x7FFFFFFFFFFFFFFFUL)
291 #else
292 		if (tot_len > 0x7FFFFFFFUL)
293 #endif
294 			goto out;
295 	}
296 
297 	/* VERIFY_WRITE actually means a read, as we write to user space */
298 	ret = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
299 				file, &file->f_pos, tot_len);
300 	if (ret)
301 		goto out;
302 
303 	fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
304 	if (fnv) {
305 		ret = fnv(file, iov, count, &file->f_pos);
306 		goto out;
307 	}
308 
309 	/* VERIFY_WRITE actually means a read, as we write to user space */
310 	fn = (type == VERIFY_WRITE ? file->f_op->read :
311 	      (io_fn_t) file->f_op->write);
312 
313 	ret = 0;
314 	vector = iov;
315 	while (count > 0) {
316 		void * base;
317 		size_t len;
318 		ssize_t nr;
319 
320 		base = vector->iov_base;
321 		len = vector->iov_len;
322 		vector++;
323 		count--;
324 
325 		nr = fn(file, base, len, &file->f_pos);
326 
327 		if (nr < 0) {
328 			if (!ret) ret = nr;
329 			break;
330 		}
331 		ret += nr;
332 		if (nr != len)
333 			break;
334 	}
335 
336 out:
337 	if (iov != iovstack)
338 		kfree(iov);
339 out_nofree:
340 	/* VERIFY_WRITE actually means a read, as we write to user space */
341 	if ((ret + (type == VERIFY_WRITE)) > 0)
342 		dnotify_parent(file->f_dentry,
343 			(type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY);
344 	return ret;
345 }
346 
sys_readv(unsigned long fd,const struct iovec * vector,unsigned long count)347 asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector,
348 			     unsigned long count)
349 {
350 	struct file * file;
351 	ssize_t ret;
352 
353 
354 	ret = -EBADF;
355 	file = fget(fd);
356 	if (!file)
357 		goto bad_file;
358 	if (file->f_op && (file->f_mode & FMODE_READ) &&
359 	    (file->f_op->readv || file->f_op->read))
360 		ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
361 	fput(file);
362 
363 bad_file:
364 	return ret;
365 }
366 
sys_writev(unsigned long fd,const struct iovec * vector,unsigned long count)367 asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
368 			      unsigned long count)
369 {
370 	struct file * file;
371 	ssize_t ret;
372 
373 
374 	ret = -EBADF;
375 	file = fget(fd);
376 	if (!file)
377 		goto bad_file;
378 	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
379 	    (file->f_op->writev || file->f_op->write))
380 		ret = do_readv_writev(VERIFY_READ, file, vector, count);
381 	fput(file);
382 
383 bad_file:
384 	return ret;
385 }
386 
387 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
388    lseek back to original location.  They fail just like lseek does on
389    non-seekable files.  */
390 
sys_pread(unsigned int fd,char * buf,size_t count,loff_t pos)391 asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
392 			     size_t count, loff_t pos)
393 {
394 	ssize_t ret;
395 	struct file * file;
396 	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
397 
398 	ret = -EBADF;
399 	file = fget(fd);
400 	if (!file)
401 		goto bad_file;
402 	if (!(file->f_mode & FMODE_READ))
403 		goto out;
404 	ret = rw_verify_area(READ, file, &pos, count);
405 
406 	if (ret)
407 		goto out;
408 	ret = -EINVAL;
409 	if (!file->f_op || !(read = file->f_op->read))
410 		goto out;
411 	if (pos < 0)
412 		goto out;
413 	ret = read(file, buf, count, &pos);
414 	if (ret > 0)
415 		dnotify_parent(file->f_dentry, DN_ACCESS);
416 out:
417 	fput(file);
418 bad_file:
419 	return ret;
420 }
421 
sys_pwrite(unsigned int fd,const char * buf,size_t count,loff_t pos)422 asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
423 			      size_t count, loff_t pos)
424 {
425 	ssize_t ret;
426 	struct file * file;
427 	ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
428 
429 	ret = -EBADF;
430 	file = fget(fd);
431 	if (!file)
432 		goto bad_file;
433 	if (!(file->f_mode & FMODE_WRITE))
434 		goto out;
435 	ret = rw_verify_area(WRITE, file, &pos, count);
436 
437 	if (ret)
438 		goto out;
439 	ret = -EINVAL;
440 	if (!file->f_op || !(write = file->f_op->write))
441 		goto out;
442 	if (pos < 0)
443 		goto out;
444 
445 	ret = write(file, buf, count, &pos);
446 	if (ret > 0)
447 		dnotify_parent(file->f_dentry, DN_MODIFY);
448 out:
449 	fput(file);
450 bad_file:
451 	return ret;
452 }
453