1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 1995 Linus Torvalds
8 #include <linux/stddef.h>
9 #include <linux/kernel.h>
10 #include <linux/export.h>
11 #include <linux/time.h>
13 #include <linux/errno.h>
14 #include <linux/stat.h>
15 #include <linux/file.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>
24 #include <linux/uaccess.h>
26 int iterate_dir(struct file *file, struct dir_context *ctx)
28 struct inode *inode = file_inode(file);
31 if (file->f_op->iterate_shared)
33 else if (!file->f_op->iterate)
36 res = security_file_permission(file, MAY_READ);
41 res = down_read_killable(&inode->i_rwsem);
43 res = down_write_killable(&inode->i_rwsem);
48 if (!IS_DEADDIR(inode)) {
49 ctx->pos = file->f_pos;
51 res = file->f_op->iterate_shared(file, ctx);
53 res = file->f_op->iterate(file, ctx);
54 file->f_pos = ctx->pos;
55 fsnotify_access(file);
59 inode_unlock_shared(inode);
65 EXPORT_SYMBOL(iterate_dir);
68 * POSIX says that a dirent name cannot contain NULL or a '/'.
70 * It's not 100% clear what we should really do in this case.
71 * The filesystem is clearly corrupted, but returning a hard
72 * error means that you now don't see any of the other names
73 * either, so that isn't a perfect alternative.
75 * And if you return an error, what error do you use? Several
76 * filesystems seem to have decided on EUCLEAN being the error
77 * code for EFSCORRUPTED, and that may be the error to use. Or
78 * just EIO, which is perhaps more obvious to users.
80 * In order to see the other file names in the directory, the
81 * caller might want to make this a "soft" error: skip the
82 * entry, and return the error at the end instead.
84 * Note that this should likely do a "memchr(name, 0, len)"
85 * check too, since that would be filesystem corruption as
86 * well. However, that case can't actually confuse user space,
87 * which has to do a strlen() on the name anyway to find the
88 * filename length, and the above "soft error" worry means
89 * that it's probably better left alone until we have that
92 static int verify_dirent_name(const char *name, int len)
96 if (memchr(name, '/', len))
102 * Traditional linux readdir() handling..
104 * "count=1" is a special case, meaning that the buffer is one
105 * dirent-structure in size and that the code can't handle more
106 * anyway. Thus the special "fillonedir()" function for that
107 * case (the low-level handlers don't need to care about this).
110 #ifdef __ARCH_WANT_OLD_READDIR
112 struct old_linux_dirent {
114 unsigned long d_offset;
115 unsigned short d_namlen;
119 struct readdir_callback {
120 struct dir_context ctx;
121 struct old_linux_dirent __user * dirent;
125 static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
126 loff_t offset, u64 ino, unsigned int d_type)
128 struct readdir_callback *buf =
129 container_of(ctx, struct readdir_callback, ctx);
130 struct old_linux_dirent __user * dirent;
135 buf->result = verify_dirent_name(name, namlen);
139 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
140 buf->result = -EOVERFLOW;
144 dirent = buf->dirent;
145 if (!access_ok(VERIFY_WRITE, dirent,
146 (unsigned long)(dirent->d_name + namlen + 1) -
147 (unsigned long)dirent))
149 if ( __put_user(d_ino, &dirent->d_ino) ||
150 __put_user(offset, &dirent->d_offset) ||
151 __put_user(namlen, &dirent->d_namlen) ||
152 __copy_to_user(dirent->d_name, name, namlen) ||
153 __put_user(0, dirent->d_name + namlen))
157 buf->result = -EFAULT;
161 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
162 struct old_linux_dirent __user *, dirent, unsigned int, count)
165 struct fd f = fdget_pos(fd);
166 struct readdir_callback buf = {
167 .ctx.actor = fillonedir,
174 error = iterate_dir(f.file, &buf.ctx);
182 #endif /* __ARCH_WANT_OLD_READDIR */
185 * New, all-improved, singing, dancing, iBCS2-compliant getdents()
188 struct linux_dirent {
191 unsigned short d_reclen;
195 struct getdents_callback {
196 struct dir_context ctx;
197 struct linux_dirent __user * current_dir;
198 struct linux_dirent __user * previous;
203 static int filldir(struct dir_context *ctx, const char *name, int namlen,
204 loff_t offset, u64 ino, unsigned int d_type)
206 struct linux_dirent __user * dirent;
207 struct getdents_callback *buf =
208 container_of(ctx, struct getdents_callback, ctx);
210 int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
213 buf->error = verify_dirent_name(name, namlen);
214 if (unlikely(buf->error))
216 buf->error = -EINVAL; /* only used if we fail.. */
217 if (reclen > buf->count)
220 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
221 buf->error = -EOVERFLOW;
224 dirent = buf->previous;
226 if (signal_pending(current))
228 if (__put_user(offset, &dirent->d_off))
231 dirent = buf->current_dir;
232 if (__put_user(d_ino, &dirent->d_ino))
234 if (__put_user(reclen, &dirent->d_reclen))
236 if (copy_to_user(dirent->d_name, name, namlen))
238 if (__put_user(0, dirent->d_name + namlen))
240 if (__put_user(d_type, (char __user *) dirent + reclen - 1))
242 buf->previous = dirent;
243 dirent = (void __user *)dirent + reclen;
244 buf->current_dir = dirent;
245 buf->count -= reclen;
248 buf->error = -EFAULT;
252 SYSCALL_DEFINE3(getdents, unsigned int, fd,
253 struct linux_dirent __user *, dirent, unsigned int, count)
256 struct linux_dirent __user * lastdirent;
257 struct getdents_callback buf = {
258 .ctx.actor = filldir,
260 .current_dir = dirent
264 if (!access_ok(VERIFY_WRITE, dirent, count))
271 error = iterate_dir(f.file, &buf.ctx);
274 lastdirent = buf.previous;
276 if (put_user(buf.ctx.pos, &lastdirent->d_off))
279 error = count - buf.count;
285 struct getdents_callback64 {
286 struct dir_context ctx;
287 struct linux_dirent64 __user * current_dir;
288 struct linux_dirent64 __user * previous;
293 static int filldir64(struct dir_context *ctx, const char *name, int namlen,
294 loff_t offset, u64 ino, unsigned int d_type)
296 struct linux_dirent64 __user *dirent;
297 struct getdents_callback64 *buf =
298 container_of(ctx, struct getdents_callback64, ctx);
299 int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
302 buf->error = verify_dirent_name(name, namlen);
303 if (unlikely(buf->error))
305 buf->error = -EINVAL; /* only used if we fail.. */
306 if (reclen > buf->count)
308 dirent = buf->previous;
310 if (signal_pending(current))
312 if (__put_user(offset, &dirent->d_off))
315 dirent = buf->current_dir;
316 if (__put_user(ino, &dirent->d_ino))
318 if (__put_user(0, &dirent->d_off))
320 if (__put_user(reclen, &dirent->d_reclen))
322 if (__put_user(d_type, &dirent->d_type))
324 if (copy_to_user(dirent->d_name, name, namlen))
326 if (__put_user(0, dirent->d_name + namlen))
328 buf->previous = dirent;
329 dirent = (void __user *)dirent + reclen;
330 buf->current_dir = dirent;
331 buf->count -= reclen;
334 buf->error = -EFAULT;
338 int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,
342 struct linux_dirent64 __user * lastdirent;
343 struct getdents_callback64 buf = {
344 .ctx.actor = filldir64,
346 .current_dir = dirent
350 if (!access_ok(VERIFY_WRITE, dirent, count))
357 error = iterate_dir(f.file, &buf.ctx);
360 lastdirent = buf.previous;
362 typeof(lastdirent->d_off) d_off = buf.ctx.pos;
363 if (__put_user(d_off, &lastdirent->d_off))
366 error = count - buf.count;
373 SYSCALL_DEFINE3(getdents64, unsigned int, fd,
374 struct linux_dirent64 __user *, dirent, unsigned int, count)
376 return ksys_getdents64(fd, dirent, count);
380 struct compat_old_linux_dirent {
381 compat_ulong_t d_ino;
382 compat_ulong_t d_offset;
383 unsigned short d_namlen;
387 struct compat_readdir_callback {
388 struct dir_context ctx;
389 struct compat_old_linux_dirent __user *dirent;
393 static int compat_fillonedir(struct dir_context *ctx, const char *name,
394 int namlen, loff_t offset, u64 ino,
397 struct compat_readdir_callback *buf =
398 container_of(ctx, struct compat_readdir_callback, ctx);
399 struct compat_old_linux_dirent __user *dirent;
400 compat_ulong_t d_ino;
404 buf->result = verify_dirent_name(name, namlen);
408 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
409 buf->result = -EOVERFLOW;
413 dirent = buf->dirent;
414 if (!access_ok(VERIFY_WRITE, dirent,
415 (unsigned long)(dirent->d_name + namlen + 1) -
416 (unsigned long)dirent))
418 if ( __put_user(d_ino, &dirent->d_ino) ||
419 __put_user(offset, &dirent->d_offset) ||
420 __put_user(namlen, &dirent->d_namlen) ||
421 __copy_to_user(dirent->d_name, name, namlen) ||
422 __put_user(0, dirent->d_name + namlen))
426 buf->result = -EFAULT;
430 COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
431 struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
434 struct fd f = fdget_pos(fd);
435 struct compat_readdir_callback buf = {
436 .ctx.actor = compat_fillonedir,
443 error = iterate_dir(f.file, &buf.ctx);
451 struct compat_linux_dirent {
452 compat_ulong_t d_ino;
453 compat_ulong_t d_off;
454 unsigned short d_reclen;
458 struct compat_getdents_callback {
459 struct dir_context ctx;
460 struct compat_linux_dirent __user *current_dir;
461 struct compat_linux_dirent __user *previous;
466 static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
467 loff_t offset, u64 ino, unsigned int d_type)
469 struct compat_linux_dirent __user * dirent;
470 struct compat_getdents_callback *buf =
471 container_of(ctx, struct compat_getdents_callback, ctx);
472 compat_ulong_t d_ino;
473 int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
474 namlen + 2, sizeof(compat_long_t));
476 buf->error = -EINVAL; /* only used if we fail.. */
477 if (reclen > buf->count)
480 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
481 buf->error = -EOVERFLOW;
484 dirent = buf->previous;
486 if (signal_pending(current))
488 if (__put_user(offset, &dirent->d_off))
491 dirent = buf->current_dir;
492 if (__put_user(d_ino, &dirent->d_ino))
494 if (__put_user(reclen, &dirent->d_reclen))
496 if (copy_to_user(dirent->d_name, name, namlen))
498 if (__put_user(0, dirent->d_name + namlen))
500 if (__put_user(d_type, (char __user *) dirent + reclen - 1))
502 buf->previous = dirent;
503 dirent = (void __user *)dirent + reclen;
504 buf->current_dir = dirent;
505 buf->count -= reclen;
508 buf->error = -EFAULT;
512 COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
513 struct compat_linux_dirent __user *, dirent, unsigned int, count)
516 struct compat_linux_dirent __user * lastdirent;
517 struct compat_getdents_callback buf = {
518 .ctx.actor = compat_filldir,
519 .current_dir = dirent,
524 if (!access_ok(VERIFY_WRITE, dirent, count))
531 error = iterate_dir(f.file, &buf.ctx);
534 lastdirent = buf.previous;
536 if (put_user(buf.ctx.pos, &lastdirent->d_off))
539 error = count - buf.count;