OSDN Git Service

xen-pciback: redo VF placement in the virtual topology
[android-x86/kernel.git] / fs / readdir.c
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
24 #include <linux/uaccess.h>
25
26 int iterate_dir(struct file *file, struct dir_context *ctx)
27 {
28         struct inode *inode = file_inode(file);
29         bool shared = false;
30         int res = -ENOTDIR;
31         if (file->f_op->iterate_shared)
32                 shared = true;
33         else if (!file->f_op->iterate)
34                 goto out;
35
36         res = security_file_permission(file, MAY_READ);
37         if (res)
38                 goto out;
39
40         if (shared)
41                 res = down_read_killable(&inode->i_rwsem);
42         else
43                 res = down_write_killable(&inode->i_rwsem);
44         if (res)
45                 goto out;
46
47         res = -ENOENT;
48         if (!IS_DEADDIR(inode)) {
49                 ctx->pos = file->f_pos;
50                 if (shared)
51                         res = file->f_op->iterate_shared(file, ctx);
52                 else
53                         res = file->f_op->iterate(file, ctx);
54                 file->f_pos = ctx->pos;
55                 fsnotify_access(file);
56                 file_accessed(file);
57         }
58         if (shared)
59                 inode_unlock_shared(inode);
60         else
61                 inode_unlock(inode);
62 out:
63         return res;
64 }
65 EXPORT_SYMBOL(iterate_dir);
66
67 /*
68  * POSIX says that a dirent name cannot contain NULL or a '/'.
69  *
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.
74  *
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.
79  *
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.
83  *
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
90  * issue clarified.
91  */
92 static int verify_dirent_name(const char *name, int len)
93 {
94         if (!len)
95                 return -EIO;
96         if (memchr(name, '/', len))
97                 return -EIO;
98         return 0;
99 }
100
101 /*
102  * Traditional linux readdir() handling..
103  *
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).
108  */
109
110 #ifdef __ARCH_WANT_OLD_READDIR
111
112 struct old_linux_dirent {
113         unsigned long   d_ino;
114         unsigned long   d_offset;
115         unsigned short  d_namlen;
116         char            d_name[1];
117 };
118
119 struct readdir_callback {
120         struct dir_context ctx;
121         struct old_linux_dirent __user * dirent;
122         int result;
123 };
124
125 static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
126                       loff_t offset, u64 ino, unsigned int d_type)
127 {
128         struct readdir_callback *buf =
129                 container_of(ctx, struct readdir_callback, ctx);
130         struct old_linux_dirent __user * dirent;
131         unsigned long d_ino;
132
133         if (buf->result)
134                 return -EINVAL;
135         buf->result = verify_dirent_name(name, namlen);
136         if (buf->result < 0)
137                 return buf->result;
138         d_ino = ino;
139         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
140                 buf->result = -EOVERFLOW;
141                 return -EOVERFLOW;
142         }
143         buf->result++;
144         dirent = buf->dirent;
145         if (!access_ok(VERIFY_WRITE, dirent,
146                         (unsigned long)(dirent->d_name + namlen + 1) -
147                                 (unsigned long)dirent))
148                 goto efault;
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))
154                 goto efault;
155         return 0;
156 efault:
157         buf->result = -EFAULT;
158         return -EFAULT;
159 }
160
161 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
162                 struct old_linux_dirent __user *, dirent, unsigned int, count)
163 {
164         int error;
165         struct fd f = fdget_pos(fd);
166         struct readdir_callback buf = {
167                 .ctx.actor = fillonedir,
168                 .dirent = dirent
169         };
170
171         if (!f.file)
172                 return -EBADF;
173
174         error = iterate_dir(f.file, &buf.ctx);
175         if (buf.result)
176                 error = buf.result;
177
178         fdput_pos(f);
179         return error;
180 }
181
182 #endif /* __ARCH_WANT_OLD_READDIR */
183
184 /*
185  * New, all-improved, singing, dancing, iBCS2-compliant getdents()
186  * interface. 
187  */
188 struct linux_dirent {
189         unsigned long   d_ino;
190         unsigned long   d_off;
191         unsigned short  d_reclen;
192         char            d_name[1];
193 };
194
195 struct getdents_callback {
196         struct dir_context ctx;
197         struct linux_dirent __user * current_dir;
198         struct linux_dirent __user * previous;
199         int count;
200         int error;
201 };
202
203 static int filldir(struct dir_context *ctx, const char *name, int namlen,
204                    loff_t offset, u64 ino, unsigned int d_type)
205 {
206         struct linux_dirent __user * dirent;
207         struct getdents_callback *buf =
208                 container_of(ctx, struct getdents_callback, ctx);
209         unsigned long d_ino;
210         int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
211                 sizeof(long));
212
213         buf->error = verify_dirent_name(name, namlen);
214         if (unlikely(buf->error))
215                 return buf->error;
216         buf->error = -EINVAL;   /* only used if we fail.. */
217         if (reclen > buf->count)
218                 return -EINVAL;
219         d_ino = ino;
220         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
221                 buf->error = -EOVERFLOW;
222                 return -EOVERFLOW;
223         }
224         dirent = buf->previous;
225         if (dirent) {
226                 if (signal_pending(current))
227                         return -EINTR;
228                 if (__put_user(offset, &dirent->d_off))
229                         goto efault;
230         }
231         dirent = buf->current_dir;
232         if (__put_user(d_ino, &dirent->d_ino))
233                 goto efault;
234         if (__put_user(reclen, &dirent->d_reclen))
235                 goto efault;
236         if (copy_to_user(dirent->d_name, name, namlen))
237                 goto efault;
238         if (__put_user(0, dirent->d_name + namlen))
239                 goto efault;
240         if (__put_user(d_type, (char __user *) dirent + reclen - 1))
241                 goto efault;
242         buf->previous = dirent;
243         dirent = (void __user *)dirent + reclen;
244         buf->current_dir = dirent;
245         buf->count -= reclen;
246         return 0;
247 efault:
248         buf->error = -EFAULT;
249         return -EFAULT;
250 }
251
252 SYSCALL_DEFINE3(getdents, unsigned int, fd,
253                 struct linux_dirent __user *, dirent, unsigned int, count)
254 {
255         struct fd f;
256         struct linux_dirent __user * lastdirent;
257         struct getdents_callback buf = {
258                 .ctx.actor = filldir,
259                 .count = count,
260                 .current_dir = dirent
261         };
262         int error;
263
264         if (!access_ok(VERIFY_WRITE, dirent, count))
265                 return -EFAULT;
266
267         f = fdget_pos(fd);
268         if (!f.file)
269                 return -EBADF;
270
271         error = iterate_dir(f.file, &buf.ctx);
272         if (error >= 0)
273                 error = buf.error;
274         lastdirent = buf.previous;
275         if (lastdirent) {
276                 if (put_user(buf.ctx.pos, &lastdirent->d_off))
277                         error = -EFAULT;
278                 else
279                         error = count - buf.count;
280         }
281         fdput_pos(f);
282         return error;
283 }
284
285 struct getdents_callback64 {
286         struct dir_context ctx;
287         struct linux_dirent64 __user * current_dir;
288         struct linux_dirent64 __user * previous;
289         int count;
290         int error;
291 };
292
293 static int filldir64(struct dir_context *ctx, const char *name, int namlen,
294                      loff_t offset, u64 ino, unsigned int d_type)
295 {
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,
300                 sizeof(u64));
301
302         buf->error = verify_dirent_name(name, namlen);
303         if (unlikely(buf->error))
304                 return buf->error;
305         buf->error = -EINVAL;   /* only used if we fail.. */
306         if (reclen > buf->count)
307                 return -EINVAL;
308         dirent = buf->previous;
309         if (dirent) {
310                 if (signal_pending(current))
311                         return -EINTR;
312                 if (__put_user(offset, &dirent->d_off))
313                         goto efault;
314         }
315         dirent = buf->current_dir;
316         if (__put_user(ino, &dirent->d_ino))
317                 goto efault;
318         if (__put_user(0, &dirent->d_off))
319                 goto efault;
320         if (__put_user(reclen, &dirent->d_reclen))
321                 goto efault;
322         if (__put_user(d_type, &dirent->d_type))
323                 goto efault;
324         if (copy_to_user(dirent->d_name, name, namlen))
325                 goto efault;
326         if (__put_user(0, dirent->d_name + namlen))
327                 goto efault;
328         buf->previous = dirent;
329         dirent = (void __user *)dirent + reclen;
330         buf->current_dir = dirent;
331         buf->count -= reclen;
332         return 0;
333 efault:
334         buf->error = -EFAULT;
335         return -EFAULT;
336 }
337
338 int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,
339                     unsigned int count)
340 {
341         struct fd f;
342         struct linux_dirent64 __user * lastdirent;
343         struct getdents_callback64 buf = {
344                 .ctx.actor = filldir64,
345                 .count = count,
346                 .current_dir = dirent
347         };
348         int error;
349
350         if (!access_ok(VERIFY_WRITE, dirent, count))
351                 return -EFAULT;
352
353         f = fdget_pos(fd);
354         if (!f.file)
355                 return -EBADF;
356
357         error = iterate_dir(f.file, &buf.ctx);
358         if (error >= 0)
359                 error = buf.error;
360         lastdirent = buf.previous;
361         if (lastdirent) {
362                 typeof(lastdirent->d_off) d_off = buf.ctx.pos;
363                 if (__put_user(d_off, &lastdirent->d_off))
364                         error = -EFAULT;
365                 else
366                         error = count - buf.count;
367         }
368         fdput_pos(f);
369         return error;
370 }
371
372
373 SYSCALL_DEFINE3(getdents64, unsigned int, fd,
374                 struct linux_dirent64 __user *, dirent, unsigned int, count)
375 {
376         return ksys_getdents64(fd, dirent, count);
377 }
378
379 #ifdef CONFIG_COMPAT
380 struct compat_old_linux_dirent {
381         compat_ulong_t  d_ino;
382         compat_ulong_t  d_offset;
383         unsigned short  d_namlen;
384         char            d_name[1];
385 };
386
387 struct compat_readdir_callback {
388         struct dir_context ctx;
389         struct compat_old_linux_dirent __user *dirent;
390         int result;
391 };
392
393 static int compat_fillonedir(struct dir_context *ctx, const char *name,
394                              int namlen, loff_t offset, u64 ino,
395                              unsigned int d_type)
396 {
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;
401
402         if (buf->result)
403                 return -EINVAL;
404         buf->result = verify_dirent_name(name, namlen);
405         if (buf->result < 0)
406                 return buf->result;
407         d_ino = ino;
408         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
409                 buf->result = -EOVERFLOW;
410                 return -EOVERFLOW;
411         }
412         buf->result++;
413         dirent = buf->dirent;
414         if (!access_ok(VERIFY_WRITE, dirent,
415                         (unsigned long)(dirent->d_name + namlen + 1) -
416                                 (unsigned long)dirent))
417                 goto efault;
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))
423                 goto efault;
424         return 0;
425 efault:
426         buf->result = -EFAULT;
427         return -EFAULT;
428 }
429
430 COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
431                 struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
432 {
433         int error;
434         struct fd f = fdget_pos(fd);
435         struct compat_readdir_callback buf = {
436                 .ctx.actor = compat_fillonedir,
437                 .dirent = dirent
438         };
439
440         if (!f.file)
441                 return -EBADF;
442
443         error = iterate_dir(f.file, &buf.ctx);
444         if (buf.result)
445                 error = buf.result;
446
447         fdput_pos(f);
448         return error;
449 }
450
451 struct compat_linux_dirent {
452         compat_ulong_t  d_ino;
453         compat_ulong_t  d_off;
454         unsigned short  d_reclen;
455         char            d_name[1];
456 };
457
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;
462         int count;
463         int error;
464 };
465
466 static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
467                 loff_t offset, u64 ino, unsigned int d_type)
468 {
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));
475
476         buf->error = -EINVAL;   /* only used if we fail.. */
477         if (reclen > buf->count)
478                 return -EINVAL;
479         d_ino = ino;
480         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
481                 buf->error = -EOVERFLOW;
482                 return -EOVERFLOW;
483         }
484         dirent = buf->previous;
485         if (dirent) {
486                 if (signal_pending(current))
487                         return -EINTR;
488                 if (__put_user(offset, &dirent->d_off))
489                         goto efault;
490         }
491         dirent = buf->current_dir;
492         if (__put_user(d_ino, &dirent->d_ino))
493                 goto efault;
494         if (__put_user(reclen, &dirent->d_reclen))
495                 goto efault;
496         if (copy_to_user(dirent->d_name, name, namlen))
497                 goto efault;
498         if (__put_user(0, dirent->d_name + namlen))
499                 goto efault;
500         if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
501                 goto efault;
502         buf->previous = dirent;
503         dirent = (void __user *)dirent + reclen;
504         buf->current_dir = dirent;
505         buf->count -= reclen;
506         return 0;
507 efault:
508         buf->error = -EFAULT;
509         return -EFAULT;
510 }
511
512 COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
513                 struct compat_linux_dirent __user *, dirent, unsigned int, count)
514 {
515         struct fd f;
516         struct compat_linux_dirent __user * lastdirent;
517         struct compat_getdents_callback buf = {
518                 .ctx.actor = compat_filldir,
519                 .current_dir = dirent,
520                 .count = count
521         };
522         int error;
523
524         if (!access_ok(VERIFY_WRITE, dirent, count))
525                 return -EFAULT;
526
527         f = fdget_pos(fd);
528         if (!f.file)
529                 return -EBADF;
530
531         error = iterate_dir(f.file, &buf.ctx);
532         if (error >= 0)
533                 error = buf.error;
534         lastdirent = buf.previous;
535         if (lastdirent) {
536                 if (put_user(buf.ctx.pos, &lastdirent->d_off))
537                         error = -EFAULT;
538                 else
539                         error = count - buf.count;
540         }
541         fdput_pos(f);
542         return error;
543 }
544 #endif