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