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 0 : int iterate_dir(struct file *file, struct dir_context *ctx)
41 : {
42 0 : struct inode *inode = file_inode(file);
43 0 : bool shared = false;
44 0 : int res = -ENOTDIR;
45 0 : if (file->f_op->iterate_shared)
46 : shared = true;
47 0 : else if (!file->f_op->iterate)
48 : goto out;
49 :
50 0 : res = security_file_permission(file, MAY_READ);
51 : if (res)
52 : goto out;
53 :
54 0 : if (shared)
55 0 : res = down_read_killable(&inode->i_rwsem);
56 : else
57 0 : res = down_write_killable(&inode->i_rwsem);
58 0 : if (res)
59 : goto out;
60 :
61 0 : res = -ENOENT;
62 0 : if (!IS_DEADDIR(inode)) {
63 0 : ctx->pos = file->f_pos;
64 0 : if (shared)
65 0 : res = file->f_op->iterate_shared(file, ctx);
66 : else
67 0 : res = file->f_op->iterate(file, ctx);
68 0 : file->f_pos = ctx->pos;
69 0 : fsnotify_access(file);
70 : file_accessed(file);
71 : }
72 0 : if (shared)
73 : inode_unlock_shared(inode);
74 : else
75 : inode_unlock(inode);
76 : out:
77 0 : 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 0 : static int verify_dirent_name(const char *name, int len)
111 : {
112 0 : if (len <= 0 || len >= PATH_MAX)
113 : return -EIO;
114 0 : if (memchr(name, '/', len))
115 : return -EIO;
116 0 : 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[];
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 bool 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 : struct old_linux_dirent __user * dirent;
149 : unsigned long d_ino;
150 :
151 0 : if (buf->result)
152 : return false;
153 0 : buf->result = verify_dirent_name(name, namlen);
154 0 : if (buf->result)
155 : return false;
156 0 : d_ino = ino;
157 : if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
158 : buf->result = -EOVERFLOW;
159 : return false;
160 : }
161 0 : buf->result++;
162 0 : dirent = buf->dirent;
163 0 : if (!user_write_access_begin(dirent,
164 : (unsigned long)(dirent->d_name + namlen + 1) -
165 : (unsigned long)dirent))
166 : goto efault;
167 0 : unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
168 0 : unsafe_put_user(offset, &dirent->d_offset, efault_end);
169 0 : unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
170 0 : unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
171 : user_write_access_end();
172 : return true;
173 : efault_end:
174 : user_write_access_end();
175 : efault:
176 0 : buf->result = -EFAULT;
177 0 : return false;
178 : }
179 :
180 0 : SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
181 : struct old_linux_dirent __user *, dirent, unsigned int, count)
182 : {
183 : int error;
184 0 : struct fd f = fdget_pos(fd);
185 0 : struct readdir_callback buf = {
186 : .ctx.actor = fillonedir,
187 : .dirent = dirent
188 : };
189 :
190 0 : if (!f.file)
191 : return -EBADF;
192 :
193 0 : error = iterate_dir(f.file, &buf.ctx);
194 0 : if (buf.result)
195 0 : error = buf.result;
196 :
197 0 : fdput_pos(f);
198 0 : return error;
199 : }
200 :
201 : #endif /* __ARCH_WANT_OLD_READDIR */
202 :
203 : /*
204 : * New, all-improved, singing, dancing, iBCS2-compliant getdents()
205 : * interface.
206 : */
207 : struct linux_dirent {
208 : unsigned long d_ino;
209 : unsigned long d_off;
210 : unsigned short d_reclen;
211 : char d_name[];
212 : };
213 :
214 : struct getdents_callback {
215 : struct dir_context ctx;
216 : struct linux_dirent __user * current_dir;
217 : int prev_reclen;
218 : int count;
219 : int error;
220 : };
221 :
222 0 : static bool filldir(struct dir_context *ctx, const char *name, int namlen,
223 : loff_t offset, u64 ino, unsigned int d_type)
224 : {
225 : struct linux_dirent __user *dirent, *prev;
226 0 : struct getdents_callback *buf =
227 0 : container_of(ctx, struct getdents_callback, ctx);
228 : unsigned long d_ino;
229 0 : int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
230 : sizeof(long));
231 : int prev_reclen;
232 :
233 0 : buf->error = verify_dirent_name(name, namlen);
234 0 : if (unlikely(buf->error))
235 : return false;
236 0 : buf->error = -EINVAL; /* only used if we fail.. */
237 0 : if (reclen > buf->count)
238 : return false;
239 0 : d_ino = ino;
240 : if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
241 : buf->error = -EOVERFLOW;
242 : return false;
243 : }
244 0 : prev_reclen = buf->prev_reclen;
245 0 : if (prev_reclen && signal_pending(current))
246 : return false;
247 0 : dirent = buf->current_dir;
248 0 : prev = (void __user *) dirent - prev_reclen;
249 0 : if (!user_write_access_begin(prev, reclen + prev_reclen))
250 : goto efault;
251 :
252 : /* This might be 'dirent->d_off', but if so it will get overwritten */
253 0 : unsafe_put_user(offset, &prev->d_off, efault_end);
254 0 : unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
255 0 : unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
256 0 : unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
257 0 : unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
258 : user_write_access_end();
259 :
260 0 : buf->current_dir = (void __user *)dirent + reclen;
261 0 : buf->prev_reclen = reclen;
262 0 : buf->count -= reclen;
263 0 : return true;
264 : efault_end:
265 : user_write_access_end();
266 : efault:
267 0 : buf->error = -EFAULT;
268 0 : return false;
269 : }
270 :
271 0 : SYSCALL_DEFINE3(getdents, unsigned int, fd,
272 : struct linux_dirent __user *, dirent, unsigned int, count)
273 : {
274 : struct fd f;
275 0 : struct getdents_callback buf = {
276 : .ctx.actor = filldir,
277 : .count = count,
278 : .current_dir = dirent
279 : };
280 : int error;
281 :
282 0 : f = fdget_pos(fd);
283 0 : if (!f.file)
284 : return -EBADF;
285 :
286 0 : error = iterate_dir(f.file, &buf.ctx);
287 0 : if (error >= 0)
288 0 : error = buf.error;
289 0 : if (buf.prev_reclen) {
290 : struct linux_dirent __user * lastdirent;
291 0 : lastdirent = (void __user *)buf.current_dir - buf.prev_reclen;
292 :
293 0 : if (put_user(buf.ctx.pos, &lastdirent->d_off))
294 : error = -EFAULT;
295 : else
296 0 : error = count - buf.count;
297 : }
298 0 : fdput_pos(f);
299 0 : return error;
300 : }
301 :
302 : struct getdents_callback64 {
303 : struct dir_context ctx;
304 : struct linux_dirent64 __user * current_dir;
305 : int prev_reclen;
306 : int count;
307 : int error;
308 : };
309 :
310 0 : static bool filldir64(struct dir_context *ctx, const char *name, int namlen,
311 : loff_t offset, u64 ino, unsigned int d_type)
312 : {
313 : struct linux_dirent64 __user *dirent, *prev;
314 0 : struct getdents_callback64 *buf =
315 0 : container_of(ctx, struct getdents_callback64, ctx);
316 0 : int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
317 : sizeof(u64));
318 : int prev_reclen;
319 :
320 0 : buf->error = verify_dirent_name(name, namlen);
321 0 : if (unlikely(buf->error))
322 : return false;
323 0 : buf->error = -EINVAL; /* only used if we fail.. */
324 0 : if (reclen > buf->count)
325 : return false;
326 0 : prev_reclen = buf->prev_reclen;
327 0 : if (prev_reclen && signal_pending(current))
328 : return false;
329 0 : dirent = buf->current_dir;
330 0 : prev = (void __user *)dirent - prev_reclen;
331 0 : if (!user_write_access_begin(prev, reclen + prev_reclen))
332 : goto efault;
333 :
334 : /* This might be 'dirent->d_off', but if so it will get overwritten */
335 0 : unsafe_put_user(offset, &prev->d_off, efault_end);
336 0 : unsafe_put_user(ino, &dirent->d_ino, efault_end);
337 0 : unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
338 0 : unsafe_put_user(d_type, &dirent->d_type, efault_end);
339 0 : unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
340 : user_write_access_end();
341 :
342 0 : buf->prev_reclen = reclen;
343 0 : buf->current_dir = (void __user *)dirent + reclen;
344 0 : buf->count -= reclen;
345 0 : return true;
346 :
347 : efault_end:
348 : user_write_access_end();
349 : efault:
350 0 : buf->error = -EFAULT;
351 0 : return false;
352 : }
353 :
354 0 : SYSCALL_DEFINE3(getdents64, unsigned int, fd,
355 : struct linux_dirent64 __user *, dirent, unsigned int, count)
356 : {
357 : struct fd f;
358 0 : struct getdents_callback64 buf = {
359 : .ctx.actor = filldir64,
360 : .count = count,
361 : .current_dir = dirent
362 : };
363 : int error;
364 :
365 0 : f = fdget_pos(fd);
366 0 : if (!f.file)
367 : return -EBADF;
368 :
369 0 : error = iterate_dir(f.file, &buf.ctx);
370 0 : if (error >= 0)
371 0 : error = buf.error;
372 0 : if (buf.prev_reclen) {
373 : struct linux_dirent64 __user * lastdirent;
374 0 : typeof(lastdirent->d_off) d_off = buf.ctx.pos;
375 :
376 0 : lastdirent = (void __user *) buf.current_dir - buf.prev_reclen;
377 0 : if (put_user(d_off, &lastdirent->d_off))
378 : error = -EFAULT;
379 : else
380 0 : error = count - buf.count;
381 : }
382 0 : fdput_pos(f);
383 0 : return error;
384 : }
385 :
386 : #ifdef CONFIG_COMPAT
387 : struct compat_old_linux_dirent {
388 : compat_ulong_t d_ino;
389 : compat_ulong_t d_offset;
390 : unsigned short d_namlen;
391 : char d_name[];
392 : };
393 :
394 : struct compat_readdir_callback {
395 : struct dir_context ctx;
396 : struct compat_old_linux_dirent __user *dirent;
397 : int result;
398 : };
399 :
400 : static bool compat_fillonedir(struct dir_context *ctx, const char *name,
401 : int namlen, loff_t offset, u64 ino,
402 : unsigned int d_type)
403 : {
404 : struct compat_readdir_callback *buf =
405 : container_of(ctx, struct compat_readdir_callback, ctx);
406 : struct compat_old_linux_dirent __user *dirent;
407 : compat_ulong_t d_ino;
408 :
409 : if (buf->result)
410 : return false;
411 : buf->result = verify_dirent_name(name, namlen);
412 : if (buf->result)
413 : return false;
414 : d_ino = ino;
415 : if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
416 : buf->result = -EOVERFLOW;
417 : return false;
418 : }
419 : buf->result++;
420 : dirent = buf->dirent;
421 : if (!user_write_access_begin(dirent,
422 : (unsigned long)(dirent->d_name + namlen + 1) -
423 : (unsigned long)dirent))
424 : goto efault;
425 : unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
426 : unsafe_put_user(offset, &dirent->d_offset, efault_end);
427 : unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
428 : unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
429 : user_write_access_end();
430 : return true;
431 : efault_end:
432 : user_write_access_end();
433 : efault:
434 : buf->result = -EFAULT;
435 : return false;
436 : }
437 :
438 : COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
439 : struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
440 : {
441 : int error;
442 : struct fd f = fdget_pos(fd);
443 : struct compat_readdir_callback buf = {
444 : .ctx.actor = compat_fillonedir,
445 : .dirent = dirent
446 : };
447 :
448 : if (!f.file)
449 : return -EBADF;
450 :
451 : error = iterate_dir(f.file, &buf.ctx);
452 : if (buf.result)
453 : error = buf.result;
454 :
455 : fdput_pos(f);
456 : return error;
457 : }
458 :
459 : struct compat_linux_dirent {
460 : compat_ulong_t d_ino;
461 : compat_ulong_t d_off;
462 : unsigned short d_reclen;
463 : char d_name[];
464 : };
465 :
466 : struct compat_getdents_callback {
467 : struct dir_context ctx;
468 : struct compat_linux_dirent __user *current_dir;
469 : int prev_reclen;
470 : int count;
471 : int error;
472 : };
473 :
474 : static bool compat_filldir(struct dir_context *ctx, const char *name, int namlen,
475 : loff_t offset, u64 ino, unsigned int d_type)
476 : {
477 : struct compat_linux_dirent __user *dirent, *prev;
478 : struct compat_getdents_callback *buf =
479 : container_of(ctx, struct compat_getdents_callback, ctx);
480 : compat_ulong_t d_ino;
481 : int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
482 : namlen + 2, sizeof(compat_long_t));
483 : int prev_reclen;
484 :
485 : buf->error = verify_dirent_name(name, namlen);
486 : if (unlikely(buf->error))
487 : return false;
488 : buf->error = -EINVAL; /* only used if we fail.. */
489 : if (reclen > buf->count)
490 : return false;
491 : d_ino = ino;
492 : if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
493 : buf->error = -EOVERFLOW;
494 : return false;
495 : }
496 : prev_reclen = buf->prev_reclen;
497 : if (prev_reclen && signal_pending(current))
498 : return false;
499 : dirent = buf->current_dir;
500 : prev = (void __user *) dirent - prev_reclen;
501 : if (!user_write_access_begin(prev, reclen + prev_reclen))
502 : goto efault;
503 :
504 : unsafe_put_user(offset, &prev->d_off, efault_end);
505 : unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
506 : unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
507 : unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
508 : unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
509 : user_write_access_end();
510 :
511 : buf->prev_reclen = reclen;
512 : buf->current_dir = (void __user *)dirent + reclen;
513 : buf->count -= reclen;
514 : return true;
515 : efault_end:
516 : user_write_access_end();
517 : efault:
518 : buf->error = -EFAULT;
519 : return false;
520 : }
521 :
522 : COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
523 : struct compat_linux_dirent __user *, dirent, unsigned int, count)
524 : {
525 : struct fd f;
526 : struct compat_getdents_callback buf = {
527 : .ctx.actor = compat_filldir,
528 : .current_dir = dirent,
529 : .count = count
530 : };
531 : int error;
532 :
533 : f = fdget_pos(fd);
534 : if (!f.file)
535 : return -EBADF;
536 :
537 : error = iterate_dir(f.file, &buf.ctx);
538 : if (error >= 0)
539 : error = buf.error;
540 : if (buf.prev_reclen) {
541 : struct compat_linux_dirent __user * lastdirent;
542 : lastdirent = (void __user *)buf.current_dir - buf.prev_reclen;
543 :
544 : if (put_user(buf.ctx.pos, &lastdirent->d_off))
545 : error = -EFAULT;
546 : else
547 : error = count - buf.count;
548 : }
549 : fdput_pos(f);
550 : return error;
551 : }
552 : #endif
|