xref: /openbmc/linux/fs/readdir.c (revision 3e327154)
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  * Some filesystems were never converted to '->iterate_shared()'
29  * and their directory iterators want the inode lock held for
30  * writing. This wrapper allows for converting from the shared
31  * semantics to the exclusive inode use.
32  */
wrap_directory_iterator(struct file * file,struct dir_context * ctx,int (* iter)(struct file *,struct dir_context *))33 int wrap_directory_iterator(struct file *file,
34 			    struct dir_context *ctx,
35 			    int (*iter)(struct file *, struct dir_context *))
36 {
37 	struct inode *inode = file_inode(file);
38 	int ret;
39 
40 	/*
41 	 * We'd love to have an 'inode_upgrade_trylock()' operation,
42 	 * see the comment in mmap_upgrade_trylock() in mm/memory.c.
43 	 *
44 	 * But considering this is for "filesystems that never got
45 	 * converted", it really doesn't matter.
46 	 *
47 	 * Also note that since we have to return with the lock held
48 	 * for reading, we can't use the "killable()" locking here,
49 	 * since we do need to get the lock even if we're dying.
50 	 *
51 	 * We could do the write part killably and then get the read
52 	 * lock unconditionally if it mattered, but see above on why
53 	 * this does the very simplistic conversion.
54 	 */
55 	up_read(&inode->i_rwsem);
56 	down_write(&inode->i_rwsem);
57 
58 	/*
59 	 * Since we dropped the inode lock, we should do the
60 	 * DEADDIR test again. See 'iterate_dir()' below.
61 	 *
62 	 * Note that we don't need to re-do the f_pos games,
63 	 * since the file must be locked wrt f_pos anyway.
64 	 */
65 	ret = -ENOENT;
66 	if (!IS_DEADDIR(inode))
67 		ret = iter(file, ctx);
68 
69 	downgrade_write(&inode->i_rwsem);
70 	return ret;
71 }
72 EXPORT_SYMBOL(wrap_directory_iterator);
73 
74 /*
75  * Note the "unsafe_put_user() semantics: we goto a
76  * label for errors.
77  */
78 #define unsafe_copy_dirent_name(_dst, _src, _len, label) do {	\
79 	char __user *dst = (_dst);				\
80 	const char *src = (_src);				\
81 	size_t len = (_len);					\
82 	unsafe_put_user(0, dst+len, label);			\
83 	unsafe_copy_to_user(dst, src, len, label);		\
84 } while (0)
85 
86 
iterate_dir(struct file * file,struct dir_context * ctx)87 int iterate_dir(struct file *file, struct dir_context *ctx)
88 {
89 	struct inode *inode = file_inode(file);
90 	int res = -ENOTDIR;
91 
92 	if (!file->f_op->iterate_shared)
93 		goto out;
94 
95 	res = security_file_permission(file, MAY_READ);
96 	if (res)
97 		goto out;
98 
99 	res = down_read_killable(&inode->i_rwsem);
100 	if (res)
101 		goto out;
102 
103 	res = -ENOENT;
104 	if (!IS_DEADDIR(inode)) {
105 		ctx->pos = file->f_pos;
106 		res = file->f_op->iterate_shared(file, ctx);
107 		file->f_pos = ctx->pos;
108 		fsnotify_access(file);
109 		file_accessed(file);
110 	}
111 	inode_unlock_shared(inode);
112 out:
113 	return res;
114 }
115 EXPORT_SYMBOL(iterate_dir);
116 
117 /*
118  * POSIX says that a dirent name cannot contain NULL or a '/'.
119  *
120  * It's not 100% clear what we should really do in this case.
121  * The filesystem is clearly corrupted, but returning a hard
122  * error means that you now don't see any of the other names
123  * either, so that isn't a perfect alternative.
124  *
125  * And if you return an error, what error do you use? Several
126  * filesystems seem to have decided on EUCLEAN being the error
127  * code for EFSCORRUPTED, and that may be the error to use. Or
128  * just EIO, which is perhaps more obvious to users.
129  *
130  * In order to see the other file names in the directory, the
131  * caller might want to make this a "soft" error: skip the
132  * entry, and return the error at the end instead.
133  *
134  * Note that this should likely do a "memchr(name, 0, len)"
135  * check too, since that would be filesystem corruption as
136  * well. However, that case can't actually confuse user space,
137  * which has to do a strlen() on the name anyway to find the
138  * filename length, and the above "soft error" worry means
139  * that it's probably better left alone until we have that
140  * issue clarified.
141  *
142  * Note the PATH_MAX check - it's arbitrary but the real
143  * kernel limit on a possible path component, not NAME_MAX,
144  * which is the technical standard limit.
145  */
verify_dirent_name(const char * name,int len)146 static int verify_dirent_name(const char *name, int len)
147 {
148 	if (len <= 0 || len >= PATH_MAX)
149 		return -EIO;
150 	if (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[];
171 };
172 
173 struct readdir_callback {
174 	struct dir_context ctx;
175 	struct old_linux_dirent __user * dirent;
176 	int result;
177 };
178 
fillonedir(struct dir_context * ctx,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)179 static bool 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 false;
189 	buf->result = verify_dirent_name(name, namlen);
190 	if (buf->result)
191 		return false;
192 	d_ino = ino;
193 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
194 		buf->result = -EOVERFLOW;
195 		return false;
196 	}
197 	buf->result++;
198 	dirent = buf->dirent;
199 	if (!user_write_access_begin(dirent,
200 			(unsigned long)(dirent->d_name + namlen + 1) -
201 				(unsigned long)dirent))
202 		goto efault;
203 	unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
204 	unsafe_put_user(offset, &dirent->d_offset, efault_end);
205 	unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
206 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
207 	user_write_access_end();
208 	return true;
209 efault_end:
210 	user_write_access_end();
211 efault:
212 	buf->result = -EFAULT;
213 	return false;
214 }
215 
SYSCALL_DEFINE3(old_readdir,unsigned int,fd,struct old_linux_dirent __user *,dirent,unsigned int,count)216 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
217 		struct old_linux_dirent __user *, dirent, unsigned int, count)
218 {
219 	int error;
220 	struct fd f = fdget_pos(fd);
221 	struct readdir_callback buf = {
222 		.ctx.actor = fillonedir,
223 		.dirent = dirent
224 	};
225 
226 	if (!f.file)
227 		return -EBADF;
228 
229 	error = iterate_dir(f.file, &buf.ctx);
230 	if (buf.result)
231 		error = buf.result;
232 
233 	fdput_pos(f);
234 	return error;
235 }
236 
237 #endif /* __ARCH_WANT_OLD_READDIR */
238 
239 /*
240  * New, all-improved, singing, dancing, iBCS2-compliant getdents()
241  * interface.
242  */
243 struct linux_dirent {
244 	unsigned long	d_ino;
245 	unsigned long	d_off;
246 	unsigned short	d_reclen;
247 	char		d_name[];
248 };
249 
250 struct getdents_callback {
251 	struct dir_context ctx;
252 	struct linux_dirent __user * current_dir;
253 	int prev_reclen;
254 	int count;
255 	int error;
256 };
257 
filldir(struct dir_context * ctx,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)258 static bool filldir(struct dir_context *ctx, const char *name, int namlen,
259 		   loff_t offset, u64 ino, unsigned int d_type)
260 {
261 	struct linux_dirent __user *dirent, *prev;
262 	struct getdents_callback *buf =
263 		container_of(ctx, struct getdents_callback, ctx);
264 	unsigned long d_ino;
265 	int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
266 		sizeof(long));
267 	int prev_reclen;
268 
269 	buf->error = verify_dirent_name(name, namlen);
270 	if (unlikely(buf->error))
271 		return false;
272 	buf->error = -EINVAL;	/* only used if we fail.. */
273 	if (reclen > buf->count)
274 		return false;
275 	d_ino = ino;
276 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
277 		buf->error = -EOVERFLOW;
278 		return false;
279 	}
280 	prev_reclen = buf->prev_reclen;
281 	if (prev_reclen && signal_pending(current))
282 		return false;
283 	dirent = buf->current_dir;
284 	prev = (void __user *) dirent - prev_reclen;
285 	if (!user_write_access_begin(prev, reclen + prev_reclen))
286 		goto efault;
287 
288 	/* This might be 'dirent->d_off', but if so it will get overwritten */
289 	unsafe_put_user(offset, &prev->d_off, efault_end);
290 	unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
291 	unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
292 	unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
293 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
294 	user_write_access_end();
295 
296 	buf->current_dir = (void __user *)dirent + reclen;
297 	buf->prev_reclen = reclen;
298 	buf->count -= reclen;
299 	return true;
300 efault_end:
301 	user_write_access_end();
302 efault:
303 	buf->error = -EFAULT;
304 	return false;
305 }
306 
SYSCALL_DEFINE3(getdents,unsigned int,fd,struct linux_dirent __user *,dirent,unsigned int,count)307 SYSCALL_DEFINE3(getdents, unsigned int, fd,
308 		struct linux_dirent __user *, dirent, unsigned int, count)
309 {
310 	struct fd f;
311 	struct getdents_callback buf = {
312 		.ctx.actor = filldir,
313 		.count = count,
314 		.current_dir = dirent
315 	};
316 	int error;
317 
318 	f = fdget_pos(fd);
319 	if (!f.file)
320 		return -EBADF;
321 
322 	error = iterate_dir(f.file, &buf.ctx);
323 	if (error >= 0)
324 		error = buf.error;
325 	if (buf.prev_reclen) {
326 		struct linux_dirent __user * lastdirent;
327 		lastdirent = (void __user *)buf.current_dir - buf.prev_reclen;
328 
329 		if (put_user(buf.ctx.pos, &lastdirent->d_off))
330 			error = -EFAULT;
331 		else
332 			error = count - buf.count;
333 	}
334 	fdput_pos(f);
335 	return error;
336 }
337 
338 struct getdents_callback64 {
339 	struct dir_context ctx;
340 	struct linux_dirent64 __user * current_dir;
341 	int prev_reclen;
342 	int count;
343 	int error;
344 };
345 
filldir64(struct dir_context * ctx,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)346 static bool filldir64(struct dir_context *ctx, const char *name, int namlen,
347 		     loff_t offset, u64 ino, unsigned int d_type)
348 {
349 	struct linux_dirent64 __user *dirent, *prev;
350 	struct getdents_callback64 *buf =
351 		container_of(ctx, struct getdents_callback64, ctx);
352 	int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
353 		sizeof(u64));
354 	int prev_reclen;
355 
356 	buf->error = verify_dirent_name(name, namlen);
357 	if (unlikely(buf->error))
358 		return false;
359 	buf->error = -EINVAL;	/* only used if we fail.. */
360 	if (reclen > buf->count)
361 		return false;
362 	prev_reclen = buf->prev_reclen;
363 	if (prev_reclen && signal_pending(current))
364 		return false;
365 	dirent = buf->current_dir;
366 	prev = (void __user *)dirent - prev_reclen;
367 	if (!user_write_access_begin(prev, reclen + prev_reclen))
368 		goto efault;
369 
370 	/* This might be 'dirent->d_off', but if so it will get overwritten */
371 	unsafe_put_user(offset, &prev->d_off, efault_end);
372 	unsafe_put_user(ino, &dirent->d_ino, efault_end);
373 	unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
374 	unsafe_put_user(d_type, &dirent->d_type, efault_end);
375 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
376 	user_write_access_end();
377 
378 	buf->prev_reclen = reclen;
379 	buf->current_dir = (void __user *)dirent + reclen;
380 	buf->count -= reclen;
381 	return true;
382 
383 efault_end:
384 	user_write_access_end();
385 efault:
386 	buf->error = -EFAULT;
387 	return false;
388 }
389 
SYSCALL_DEFINE3(getdents64,unsigned int,fd,struct linux_dirent64 __user *,dirent,unsigned int,count)390 SYSCALL_DEFINE3(getdents64, unsigned int, fd,
391 		struct linux_dirent64 __user *, dirent, unsigned int, count)
392 {
393 	struct fd f;
394 	struct getdents_callback64 buf = {
395 		.ctx.actor = filldir64,
396 		.count = count,
397 		.current_dir = dirent
398 	};
399 	int error;
400 
401 	f = fdget_pos(fd);
402 	if (!f.file)
403 		return -EBADF;
404 
405 	error = iterate_dir(f.file, &buf.ctx);
406 	if (error >= 0)
407 		error = buf.error;
408 	if (buf.prev_reclen) {
409 		struct linux_dirent64 __user * lastdirent;
410 		typeof(lastdirent->d_off) d_off = buf.ctx.pos;
411 
412 		lastdirent = (void __user *) buf.current_dir - buf.prev_reclen;
413 		if (put_user(d_off, &lastdirent->d_off))
414 			error = -EFAULT;
415 		else
416 			error = count - buf.count;
417 	}
418 	fdput_pos(f);
419 	return error;
420 }
421 
422 #ifdef CONFIG_COMPAT
423 struct compat_old_linux_dirent {
424 	compat_ulong_t	d_ino;
425 	compat_ulong_t	d_offset;
426 	unsigned short	d_namlen;
427 	char		d_name[];
428 };
429 
430 struct compat_readdir_callback {
431 	struct dir_context ctx;
432 	struct compat_old_linux_dirent __user *dirent;
433 	int result;
434 };
435 
compat_fillonedir(struct dir_context * ctx,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)436 static bool compat_fillonedir(struct dir_context *ctx, const char *name,
437 			     int namlen, loff_t offset, u64 ino,
438 			     unsigned int d_type)
439 {
440 	struct compat_readdir_callback *buf =
441 		container_of(ctx, struct compat_readdir_callback, ctx);
442 	struct compat_old_linux_dirent __user *dirent;
443 	compat_ulong_t d_ino;
444 
445 	if (buf->result)
446 		return false;
447 	buf->result = verify_dirent_name(name, namlen);
448 	if (buf->result)
449 		return false;
450 	d_ino = ino;
451 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
452 		buf->result = -EOVERFLOW;
453 		return false;
454 	}
455 	buf->result++;
456 	dirent = buf->dirent;
457 	if (!user_write_access_begin(dirent,
458 			(unsigned long)(dirent->d_name + namlen + 1) -
459 				(unsigned long)dirent))
460 		goto efault;
461 	unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
462 	unsafe_put_user(offset, &dirent->d_offset, efault_end);
463 	unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
464 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
465 	user_write_access_end();
466 	return true;
467 efault_end:
468 	user_write_access_end();
469 efault:
470 	buf->result = -EFAULT;
471 	return false;
472 }
473 
COMPAT_SYSCALL_DEFINE3(old_readdir,unsigned int,fd,struct compat_old_linux_dirent __user *,dirent,unsigned int,count)474 COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
475 		struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
476 {
477 	int error;
478 	struct fd f = fdget_pos(fd);
479 	struct compat_readdir_callback buf = {
480 		.ctx.actor = compat_fillonedir,
481 		.dirent = dirent
482 	};
483 
484 	if (!f.file)
485 		return -EBADF;
486 
487 	error = iterate_dir(f.file, &buf.ctx);
488 	if (buf.result)
489 		error = buf.result;
490 
491 	fdput_pos(f);
492 	return error;
493 }
494 
495 struct compat_linux_dirent {
496 	compat_ulong_t	d_ino;
497 	compat_ulong_t	d_off;
498 	unsigned short	d_reclen;
499 	char		d_name[];
500 };
501 
502 struct compat_getdents_callback {
503 	struct dir_context ctx;
504 	struct compat_linux_dirent __user *current_dir;
505 	int prev_reclen;
506 	int count;
507 	int error;
508 };
509 
compat_filldir(struct dir_context * ctx,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)510 static bool compat_filldir(struct dir_context *ctx, const char *name, int namlen,
511 		loff_t offset, u64 ino, unsigned int d_type)
512 {
513 	struct compat_linux_dirent __user *dirent, *prev;
514 	struct compat_getdents_callback *buf =
515 		container_of(ctx, struct compat_getdents_callback, ctx);
516 	compat_ulong_t d_ino;
517 	int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
518 		namlen + 2, sizeof(compat_long_t));
519 	int prev_reclen;
520 
521 	buf->error = verify_dirent_name(name, namlen);
522 	if (unlikely(buf->error))
523 		return false;
524 	buf->error = -EINVAL;	/* only used if we fail.. */
525 	if (reclen > buf->count)
526 		return false;
527 	d_ino = ino;
528 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
529 		buf->error = -EOVERFLOW;
530 		return false;
531 	}
532 	prev_reclen = buf->prev_reclen;
533 	if (prev_reclen && signal_pending(current))
534 		return false;
535 	dirent = buf->current_dir;
536 	prev = (void __user *) dirent - prev_reclen;
537 	if (!user_write_access_begin(prev, reclen + prev_reclen))
538 		goto efault;
539 
540 	unsafe_put_user(offset, &prev->d_off, efault_end);
541 	unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
542 	unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
543 	unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
544 	unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
545 	user_write_access_end();
546 
547 	buf->prev_reclen = reclen;
548 	buf->current_dir = (void __user *)dirent + reclen;
549 	buf->count -= reclen;
550 	return true;
551 efault_end:
552 	user_write_access_end();
553 efault:
554 	buf->error = -EFAULT;
555 	return false;
556 }
557 
COMPAT_SYSCALL_DEFINE3(getdents,unsigned int,fd,struct compat_linux_dirent __user *,dirent,unsigned int,count)558 COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
559 		struct compat_linux_dirent __user *, dirent, unsigned int, count)
560 {
561 	struct fd f;
562 	struct compat_getdents_callback buf = {
563 		.ctx.actor = compat_filldir,
564 		.current_dir = dirent,
565 		.count = count
566 	};
567 	int error;
568 
569 	f = fdget_pos(fd);
570 	if (!f.file)
571 		return -EBADF;
572 
573 	error = iterate_dir(f.file, &buf.ctx);
574 	if (error >= 0)
575 		error = buf.error;
576 	if (buf.prev_reclen) {
577 		struct compat_linux_dirent __user * lastdirent;
578 		lastdirent = (void __user *)buf.current_dir - buf.prev_reclen;
579 
580 		if (put_user(buf.ctx.pos, &lastdirent->d_off))
581 			error = -EFAULT;
582 		else
583 			error = count - buf.count;
584 	}
585 	fdput_pos(f);
586 	return error;
587 }
588 #endif
589