xref: /openbmc/linux/fs/readdir.c (revision 8a23eb80)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/readdir.c
4  *
5  *  Copyright (C) 1995  Linus Torvalds
6  */
7 
8 #include <linux/stddef.h>
9 #include <linux/kernel.h>
10 #include <linux/export.h>
11 #include <linux/time.h>
12 #include <linux/mm.h>
13 #include <linux/errno.h>
14 #include <linux/stat.h>
15 #include <linux/file.h>
16 #include <linux/fs.h>
17 #include <linux/fsnotify.h>
18 #include <linux/dirent.h>
19 #include <linux/security.h>
20 #include <linux/syscalls.h>
21 #include <linux/unistd.h>
22 #include <linux/compat.h>
23 #include <linux/uaccess.h>
24 
25 #include <asm/unaligned.h>
26 
27 /*
28  * Note the "unsafe_put_user() semantics: we goto a
29  * label for errors.
30  *
31  * Also note how we use a "while()" loop here, even though
32  * only the biggest size needs to loop. The compiler (well,
33  * at least gcc) is smart enough to turn the smaller sizes
34  * into just if-statements, and this way we don't need to
35  * care whether 'u64' or 'u32' is the biggest size.
36  */
37 #define unsafe_copy_loop(dst, src, len, type, label) 		\
38 	while (len >= sizeof(type)) {				\
39 		unsafe_put_user(get_unaligned((type *)src),	\
40 			(type __user *)dst, label);		\
41 		dst += sizeof(type);				\
42 		src += sizeof(type);				\
43 		len -= sizeof(type);				\
44 	}
45 
46 /*
47  * We avoid doing 64-bit copies on 32-bit architectures. They
48  * might be better, but the component names are mostly small,
49  * and the 64-bit cases can end up being much more complex and
50  * put much more register pressure on the code, so it's likely
51  * not worth the pain of unaligned accesses etc.
52  *
53  * So limit the copies to "unsigned long" size. I did verify
54  * that at least the x86-32 case is ok without this limiting,
55  * but I worry about random other legacy 32-bit cases that
56  * might not do as well.
57  */
58 #define unsafe_copy_type(dst, src, len, type, label) do {	\
59 	if (sizeof(type) <= sizeof(unsigned long))		\
60 		unsafe_copy_loop(dst, src, len, type, label);	\
61 } while (0)
62 
63 /*
64  * Copy the dirent name to user space, and NUL-terminate
65  * it. This should not be a function call, since we're doing
66  * the copy inside a "user_access_begin/end()" section.
67  */
68 #define unsafe_copy_dirent_name(_dst, _src, _len, label) do {	\
69 	char __user *dst = (_dst);				\
70 	const char *src = (_src);				\
71 	size_t len = (_len);					\
72 	unsafe_copy_type(dst, src, len, u64, label);	 	\
73 	unsafe_copy_type(dst, src, len, u32, label);		\
74 	unsafe_copy_type(dst, src, len, u16, label);		\
75 	unsafe_copy_type(dst, src, len, u8,  label);		\
76 	unsafe_put_user(0, dst, label);				\
77 } while (0)
78 
79 
80 int iterate_dir(struct file *file, struct dir_context *ctx)
81 {
82 	struct inode *inode = file_inode(file);
83 	bool shared = false;
84 	int res = -ENOTDIR;
85 	if (file->f_op->iterate_shared)
86 		shared = true;
87 	else if (!file->f_op->iterate)
88 		goto out;
89 
90 	res = security_file_permission(file, MAY_READ);
91 	if (res)
92 		goto out;
93 
94 	if (shared)
95 		res = down_read_killable(&inode->i_rwsem);
96 	else
97 		res = down_write_killable(&inode->i_rwsem);
98 	if (res)
99 		goto out;
100 
101 	res = -ENOENT;
102 	if (!IS_DEADDIR(inode)) {
103 		ctx->pos = file->f_pos;
104 		if (shared)
105 			res = file->f_op->iterate_shared(file, ctx);
106 		else
107 			res = file->f_op->iterate(file, ctx);
108 		file->f_pos = ctx->pos;
109 		fsnotify_access(file);
110 		file_accessed(file);
111 	}
112 	if (shared)
113 		inode_unlock_shared(inode);
114 	else
115 		inode_unlock(inode);
116 out:
117 	return res;
118 }
119 EXPORT_SYMBOL(iterate_dir);
120 
121 /*
122  * POSIX says that a dirent name cannot contain NULL or a '/'.
123  *
124  * It's not 100% clear what we should really do in this case.
125  * The filesystem is clearly corrupted, but returning a hard
126  * error means that you now don't see any of the other names
127  * either, so that isn't a perfect alternative.
128  *
129  * And if you return an error, what error do you use? Several
130  * filesystems seem to have decided on EUCLEAN being the error
131  * code for EFSCORRUPTED, and that may be the error to use. Or
132  * just EIO, which is perhaps more obvious to users.
133  *
134  * In order to see the other file names in the directory, the
135  * caller might want to make this a "soft" error: skip the
136  * entry, and return the error at the end instead.
137  *
138  * Note that this should likely do a "memchr(name, 0, len)"
139  * check too, since that would be filesystem corruption as
140  * well. However, that case can't actually confuse user space,
141  * which has to do a strlen() on the name anyway to find the
142  * filename length, and the above "soft error" worry means
143  * that it's probably better left alone until we have that
144  * issue clarified.
145  */
146 static int verify_dirent_name(const char *name, int len)
147 {
148 	if (WARN_ON_ONCE(!len))
149 		return -EIO;
150 	if (WARN_ON_ONCE(memchr(name, '/', len)))
151 		return -EIO;
152 	return 0;
153 }
154 
155 /*
156  * Traditional linux readdir() handling..
157  *
158  * "count=1" is a special case, meaning that the buffer is one
159  * dirent-structure in size and that the code can't handle more
160  * anyway. Thus the special "fillonedir()" function for that
161  * case (the low-level handlers don't need to care about this).
162  */
163 
164 #ifdef __ARCH_WANT_OLD_READDIR
165 
166 struct old_linux_dirent {
167 	unsigned long	d_ino;
168 	unsigned long	d_offset;
169 	unsigned short	d_namlen;
170 	char		d_name[1];
171 };
172 
173 struct readdir_callback {
174 	struct dir_context ctx;
175 	struct old_linux_dirent __user * dirent;
176 	int result;
177 };
178 
179 static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
180 		      loff_t offset, u64 ino, unsigned int d_type)
181 {
182 	struct readdir_callback *buf =
183 		container_of(ctx, struct readdir_callback, ctx);
184 	struct old_linux_dirent __user * dirent;
185 	unsigned long d_ino;
186 
187 	if (buf->result)
188 		return -EINVAL;
189 	d_ino = ino;
190 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
191 		buf->result = -EOVERFLOW;
192 		return -EOVERFLOW;
193 	}
194 	buf->result++;
195 	dirent = buf->dirent;
196 	if (!access_ok(dirent,
197 			(unsigned long)(dirent->d_name + namlen + 1) -
198 				(unsigned long)dirent))
199 		goto efault;
200 	if (	__put_user(d_ino, &dirent->d_ino) ||
201 		__put_user(offset, &dirent->d_offset) ||
202 		__put_user(namlen, &dirent->d_namlen) ||
203 		__copy_to_user(dirent->d_name, name, namlen) ||
204 		__put_user(0, dirent->d_name + namlen))
205 		goto efault;
206 	return 0;
207 efault:
208 	buf->result = -EFAULT;
209 	return -EFAULT;
210 }
211 
212 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
213 		struct old_linux_dirent __user *, dirent, unsigned int, count)
214 {
215 	int error;
216 	struct fd f = fdget_pos(fd);
217 	struct readdir_callback buf = {
218 		.ctx.actor = fillonedir,
219 		.dirent = dirent
220 	};
221 
222 	if (!f.file)
223 		return -EBADF;
224 
225 	error = iterate_dir(f.file, &buf.ctx);
226 	if (buf.result)
227 		error = buf.result;
228 
229 	fdput_pos(f);
230 	return error;
231 }
232 
233 #endif /* __ARCH_WANT_OLD_READDIR */
234 
235 /*
236  * New, all-improved, singing, dancing, iBCS2-compliant getdents()
237  * interface.
238  */
239 struct linux_dirent {
240 	unsigned long	d_ino;
241 	unsigned long	d_off;
242 	unsigned short	d_reclen;
243 	char		d_name[1];
244 };
245 
246 struct getdents_callback {
247 	struct dir_context ctx;
248 	struct linux_dirent __user * current_dir;
249 	struct linux_dirent __user * previous;
250 	int count;
251 	int error;
252 };
253 
254 static int filldir(struct dir_context *ctx, const char *name, int namlen,
255 		   loff_t offset, u64 ino, unsigned int d_type)
256 {
257 	struct linux_dirent __user * dirent;
258 	struct getdents_callback *buf =
259 		container_of(ctx, struct getdents_callback, ctx);
260 	unsigned long d_ino;
261 	int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
262 		sizeof(long));
263 
264 	buf->error = verify_dirent_name(name, namlen);
265 	if (unlikely(buf->error))
266 		return buf->error;
267 	buf->error = -EINVAL;	/* only used if we fail.. */
268 	if (reclen > buf->count)
269 		return -EINVAL;
270 	d_ino = ino;
271 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
272 		buf->error = -EOVERFLOW;
273 		return -EOVERFLOW;
274 	}
275 	dirent = buf->previous;
276 	if (dirent && signal_pending(current))
277 		return -EINTR;
278 
279 	/*
280 	 * Note! This range-checks 'previous' (which may be NULL).
281 	 * The real range was checked in getdents
282 	 */
283 	if (!user_access_begin(dirent, sizeof(*dirent)))
284 		goto efault;
285 	if (dirent)
286 		unsafe_put_user(offset, &dirent->d_off, efault_end);
287 	dirent = buf->current_dir;
288 	unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
289 	unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
290 	unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
291 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
292 	user_access_end();
293 
294 	buf->previous = dirent;
295 	dirent = (void __user *)dirent + reclen;
296 	buf->current_dir = dirent;
297 	buf->count -= reclen;
298 	return 0;
299 efault_end:
300 	user_access_end();
301 efault:
302 	buf->error = -EFAULT;
303 	return -EFAULT;
304 }
305 
306 SYSCALL_DEFINE3(getdents, unsigned int, fd,
307 		struct linux_dirent __user *, dirent, unsigned int, count)
308 {
309 	struct fd f;
310 	struct linux_dirent __user * lastdirent;
311 	struct getdents_callback buf = {
312 		.ctx.actor = filldir,
313 		.count = count,
314 		.current_dir = dirent
315 	};
316 	int error;
317 
318 	if (!access_ok(dirent, count))
319 		return -EFAULT;
320 
321 	f = fdget_pos(fd);
322 	if (!f.file)
323 		return -EBADF;
324 
325 	error = iterate_dir(f.file, &buf.ctx);
326 	if (error >= 0)
327 		error = buf.error;
328 	lastdirent = buf.previous;
329 	if (lastdirent) {
330 		if (put_user(buf.ctx.pos, &lastdirent->d_off))
331 			error = -EFAULT;
332 		else
333 			error = count - buf.count;
334 	}
335 	fdput_pos(f);
336 	return error;
337 }
338 
339 struct getdents_callback64 {
340 	struct dir_context ctx;
341 	struct linux_dirent64 __user * current_dir;
342 	struct linux_dirent64 __user * previous;
343 	int count;
344 	int error;
345 };
346 
347 static int filldir64(struct dir_context *ctx, const char *name, int namlen,
348 		     loff_t offset, u64 ino, unsigned int d_type)
349 {
350 	struct linux_dirent64 __user *dirent;
351 	struct getdents_callback64 *buf =
352 		container_of(ctx, struct getdents_callback64, ctx);
353 	int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
354 		sizeof(u64));
355 
356 	buf->error = verify_dirent_name(name, namlen);
357 	if (unlikely(buf->error))
358 		return buf->error;
359 	buf->error = -EINVAL;	/* only used if we fail.. */
360 	if (reclen > buf->count)
361 		return -EINVAL;
362 	dirent = buf->previous;
363 	if (dirent && signal_pending(current))
364 		return -EINTR;
365 
366 	/*
367 	 * Note! This range-checks 'previous' (which may be NULL).
368 	 * The real range was checked in getdents
369 	 */
370 	if (!user_access_begin(dirent, sizeof(*dirent)))
371 		goto efault;
372 	if (dirent)
373 		unsafe_put_user(offset, &dirent->d_off, efault_end);
374 	dirent = buf->current_dir;
375 	unsafe_put_user(ino, &dirent->d_ino, efault_end);
376 	unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
377 	unsafe_put_user(d_type, &dirent->d_type, efault_end);
378 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
379 	user_access_end();
380 
381 	buf->previous = dirent;
382 	dirent = (void __user *)dirent + reclen;
383 	buf->current_dir = dirent;
384 	buf->count -= reclen;
385 	return 0;
386 efault_end:
387 	user_access_end();
388 efault:
389 	buf->error = -EFAULT;
390 	return -EFAULT;
391 }
392 
393 int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,
394 		    unsigned int count)
395 {
396 	struct fd f;
397 	struct linux_dirent64 __user * lastdirent;
398 	struct getdents_callback64 buf = {
399 		.ctx.actor = filldir64,
400 		.count = count,
401 		.current_dir = dirent
402 	};
403 	int error;
404 
405 	if (!access_ok(dirent, count))
406 		return -EFAULT;
407 
408 	f = fdget_pos(fd);
409 	if (!f.file)
410 		return -EBADF;
411 
412 	error = iterate_dir(f.file, &buf.ctx);
413 	if (error >= 0)
414 		error = buf.error;
415 	lastdirent = buf.previous;
416 	if (lastdirent) {
417 		typeof(lastdirent->d_off) d_off = buf.ctx.pos;
418 		if (__put_user(d_off, &lastdirent->d_off))
419 			error = -EFAULT;
420 		else
421 			error = count - buf.count;
422 	}
423 	fdput_pos(f);
424 	return error;
425 }
426 
427 
428 SYSCALL_DEFINE3(getdents64, unsigned int, fd,
429 		struct linux_dirent64 __user *, dirent, unsigned int, count)
430 {
431 	return ksys_getdents64(fd, dirent, count);
432 }
433 
434 #ifdef CONFIG_COMPAT
435 struct compat_old_linux_dirent {
436 	compat_ulong_t	d_ino;
437 	compat_ulong_t	d_offset;
438 	unsigned short	d_namlen;
439 	char		d_name[1];
440 };
441 
442 struct compat_readdir_callback {
443 	struct dir_context ctx;
444 	struct compat_old_linux_dirent __user *dirent;
445 	int result;
446 };
447 
448 static int compat_fillonedir(struct dir_context *ctx, const char *name,
449 			     int namlen, loff_t offset, u64 ino,
450 			     unsigned int d_type)
451 {
452 	struct compat_readdir_callback *buf =
453 		container_of(ctx, struct compat_readdir_callback, ctx);
454 	struct compat_old_linux_dirent __user *dirent;
455 	compat_ulong_t d_ino;
456 
457 	if (buf->result)
458 		return -EINVAL;
459 	d_ino = ino;
460 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
461 		buf->result = -EOVERFLOW;
462 		return -EOVERFLOW;
463 	}
464 	buf->result++;
465 	dirent = buf->dirent;
466 	if (!access_ok(dirent,
467 			(unsigned long)(dirent->d_name + namlen + 1) -
468 				(unsigned long)dirent))
469 		goto efault;
470 	if (	__put_user(d_ino, &dirent->d_ino) ||
471 		__put_user(offset, &dirent->d_offset) ||
472 		__put_user(namlen, &dirent->d_namlen) ||
473 		__copy_to_user(dirent->d_name, name, namlen) ||
474 		__put_user(0, dirent->d_name + namlen))
475 		goto efault;
476 	return 0;
477 efault:
478 	buf->result = -EFAULT;
479 	return -EFAULT;
480 }
481 
482 COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
483 		struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
484 {
485 	int error;
486 	struct fd f = fdget_pos(fd);
487 	struct compat_readdir_callback buf = {
488 		.ctx.actor = compat_fillonedir,
489 		.dirent = dirent
490 	};
491 
492 	if (!f.file)
493 		return -EBADF;
494 
495 	error = iterate_dir(f.file, &buf.ctx);
496 	if (buf.result)
497 		error = buf.result;
498 
499 	fdput_pos(f);
500 	return error;
501 }
502 
503 struct compat_linux_dirent {
504 	compat_ulong_t	d_ino;
505 	compat_ulong_t	d_off;
506 	unsigned short	d_reclen;
507 	char		d_name[1];
508 };
509 
510 struct compat_getdents_callback {
511 	struct dir_context ctx;
512 	struct compat_linux_dirent __user *current_dir;
513 	struct compat_linux_dirent __user *previous;
514 	int count;
515 	int error;
516 };
517 
518 static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
519 		loff_t offset, u64 ino, unsigned int d_type)
520 {
521 	struct compat_linux_dirent __user * dirent;
522 	struct compat_getdents_callback *buf =
523 		container_of(ctx, struct compat_getdents_callback, ctx);
524 	compat_ulong_t d_ino;
525 	int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
526 		namlen + 2, sizeof(compat_long_t));
527 
528 	buf->error = -EINVAL;	/* only used if we fail.. */
529 	if (reclen > buf->count)
530 		return -EINVAL;
531 	d_ino = ino;
532 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
533 		buf->error = -EOVERFLOW;
534 		return -EOVERFLOW;
535 	}
536 	dirent = buf->previous;
537 	if (dirent) {
538 		if (signal_pending(current))
539 			return -EINTR;
540 		if (__put_user(offset, &dirent->d_off))
541 			goto efault;
542 	}
543 	dirent = buf->current_dir;
544 	if (__put_user(d_ino, &dirent->d_ino))
545 		goto efault;
546 	if (__put_user(reclen, &dirent->d_reclen))
547 		goto efault;
548 	if (copy_to_user(dirent->d_name, name, namlen))
549 		goto efault;
550 	if (__put_user(0, dirent->d_name + namlen))
551 		goto efault;
552 	if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
553 		goto efault;
554 	buf->previous = dirent;
555 	dirent = (void __user *)dirent + reclen;
556 	buf->current_dir = dirent;
557 	buf->count -= reclen;
558 	return 0;
559 efault:
560 	buf->error = -EFAULT;
561 	return -EFAULT;
562 }
563 
564 COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
565 		struct compat_linux_dirent __user *, dirent, unsigned int, count)
566 {
567 	struct fd f;
568 	struct compat_linux_dirent __user * lastdirent;
569 	struct compat_getdents_callback buf = {
570 		.ctx.actor = compat_filldir,
571 		.current_dir = dirent,
572 		.count = count
573 	};
574 	int error;
575 
576 	if (!access_ok(dirent, count))
577 		return -EFAULT;
578 
579 	f = fdget_pos(fd);
580 	if (!f.file)
581 		return -EBADF;
582 
583 	error = iterate_dir(f.file, &buf.ctx);
584 	if (error >= 0)
585 		error = buf.error;
586 	lastdirent = buf.previous;
587 	if (lastdirent) {
588 		if (put_user(buf.ctx.pos, &lastdirent->d_off))
589 			error = -EFAULT;
590 		else
591 			error = count - buf.count;
592 	}
593 	fdput_pos(f);
594 	return error;
595 }
596 #endif
597