GNU Linux-libre 4.9.333-gnu1
[releases.git] / fs / readdir.c
1 /*
2  *  linux/fs/readdir.c
3  *
4  *  Copyright (C) 1995  Linus Torvalds
5  */
6
7 #include <linux/stddef.h>
8 #include <linux/kernel.h>
9 #include <linux/export.h>
10 #include <linux/time.h>
11 #include <linux/mm.h>
12 #include <linux/errno.h>
13 #include <linux/stat.h>
14 #include <linux/file.h>
15 #include <linux/fs.h>
16 #include <linux/fsnotify.h>
17 #include <linux/dirent.h>
18 #include <linux/security.h>
19 #include <linux/syscalls.h>
20 #include <linux/unistd.h>
21
22 #include <asm/uaccess.h>
23
24 int iterate_dir(struct file *file, struct dir_context *ctx)
25 {
26         struct inode *inode = file_inode(file);
27         bool shared = false;
28         int res = -ENOTDIR;
29         if (file->f_op->iterate_shared)
30                 shared = true;
31         else if (!file->f_op->iterate)
32                 goto out;
33
34         res = security_file_permission(file, MAY_READ);
35         if (res)
36                 goto out;
37
38         if (shared) {
39                 inode_lock_shared(inode);
40         } else {
41                 res = down_write_killable(&inode->i_rwsem);
42                 if (res)
43                         goto out;
44         }
45
46         res = -ENOENT;
47         if (!IS_DEADDIR(inode)) {
48                 ctx->pos = file->f_pos;
49                 if (shared)
50                         res = file->f_op->iterate_shared(file, ctx);
51                 else
52                         res = file->f_op->iterate(file, ctx);
53                 file->f_pos = ctx->pos;
54                 fsnotify_access(file);
55                 file_accessed(file);
56         }
57         if (shared)
58                 inode_unlock_shared(inode);
59         else
60                 inode_unlock(inode);
61 out:
62         return res;
63 }
64 EXPORT_SYMBOL(iterate_dir);
65
66 /*
67  * POSIX says that a dirent name cannot contain NULL or a '/'.
68  *
69  * It's not 100% clear what we should really do in this case.
70  * The filesystem is clearly corrupted, but returning a hard
71  * error means that you now don't see any of the other names
72  * either, so that isn't a perfect alternative.
73  *
74  * And if you return an error, what error do you use? Several
75  * filesystems seem to have decided on EUCLEAN being the error
76  * code for EFSCORRUPTED, and that may be the error to use. Or
77  * just EIO, which is perhaps more obvious to users.
78  *
79  * In order to see the other file names in the directory, the
80  * caller might want to make this a "soft" error: skip the
81  * entry, and return the error at the end instead.
82  *
83  * Note that this should likely do a "memchr(name, 0, len)"
84  * check too, since that would be filesystem corruption as
85  * well. However, that case can't actually confuse user space,
86  * which has to do a strlen() on the name anyway to find the
87  * filename length, and the above "soft error" worry means
88  * that it's probably better left alone until we have that
89  * issue clarified.
90  */
91 static int verify_dirent_name(const char *name, int len)
92 {
93         if (!len)
94                 return -EIO;
95         if (memchr(name, '/', len))
96                 return -EIO;
97         return 0;
98 }
99
100 /*
101  * Traditional linux readdir() handling..
102  *
103  * "count=1" is a special case, meaning that the buffer is one
104  * dirent-structure in size and that the code can't handle more
105  * anyway. Thus the special "fillonedir()" function for that
106  * case (the low-level handlers don't need to care about this).
107  */
108
109 #ifdef __ARCH_WANT_OLD_READDIR
110
111 struct old_linux_dirent {
112         unsigned long   d_ino;
113         unsigned long   d_offset;
114         unsigned short  d_namlen;
115         char            d_name[1];
116 };
117
118 struct readdir_callback {
119         struct dir_context ctx;
120         struct old_linux_dirent __user * dirent;
121         int result;
122 };
123
124 static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
125                       loff_t offset, u64 ino, unsigned int d_type)
126 {
127         struct readdir_callback *buf =
128                 container_of(ctx, struct readdir_callback, ctx);
129         struct old_linux_dirent __user * dirent;
130         unsigned long d_ino;
131
132         if (buf->result)
133                 return -EINVAL;
134         d_ino = ino;
135         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
136                 buf->result = -EOVERFLOW;
137                 return -EOVERFLOW;
138         }
139         buf->result++;
140         dirent = buf->dirent;
141         if (!access_ok(VERIFY_WRITE, dirent,
142                         (unsigned long)(dirent->d_name + namlen + 1) -
143                                 (unsigned long)dirent))
144                 goto efault;
145         if (    __put_user(d_ino, &dirent->d_ino) ||
146                 __put_user(offset, &dirent->d_offset) ||
147                 __put_user(namlen, &dirent->d_namlen) ||
148                 __copy_to_user(dirent->d_name, name, namlen) ||
149                 __put_user(0, dirent->d_name + namlen))
150                 goto efault;
151         return 0;
152 efault:
153         buf->result = -EFAULT;
154         return -EFAULT;
155 }
156
157 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
158                 struct old_linux_dirent __user *, dirent, unsigned int, count)
159 {
160         int error;
161         struct fd f = fdget_pos(fd);
162         struct readdir_callback buf = {
163                 .ctx.actor = fillonedir,
164                 .dirent = dirent
165         };
166
167         if (!f.file)
168                 return -EBADF;
169
170         error = iterate_dir(f.file, &buf.ctx);
171         if (buf.result)
172                 error = buf.result;
173
174         fdput_pos(f);
175         return error;
176 }
177
178 #endif /* __ARCH_WANT_OLD_READDIR */
179
180 /*
181  * New, all-improved, singing, dancing, iBCS2-compliant getdents()
182  * interface. 
183  */
184 struct linux_dirent {
185         unsigned long   d_ino;
186         unsigned long   d_off;
187         unsigned short  d_reclen;
188         char            d_name[1];
189 };
190
191 struct getdents_callback {
192         struct dir_context ctx;
193         struct linux_dirent __user * current_dir;
194         struct linux_dirent __user * previous;
195         int count;
196         int error;
197 };
198
199 static int filldir(struct dir_context *ctx, const char *name, int namlen,
200                    loff_t offset, u64 ino, unsigned int d_type)
201 {
202         struct linux_dirent __user * dirent;
203         struct getdents_callback *buf =
204                 container_of(ctx, struct getdents_callback, ctx);
205         unsigned long d_ino;
206         int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
207                 sizeof(long));
208
209         buf->error = verify_dirent_name(name, namlen);
210         if (unlikely(buf->error))
211                 return buf->error;
212         buf->error = -EINVAL;   /* only used if we fail.. */
213         if (reclen > buf->count)
214                 return -EINVAL;
215         d_ino = ino;
216         if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
217                 buf->error = -EOVERFLOW;
218                 return -EOVERFLOW;
219         }
220         dirent = buf->previous;
221         if (dirent) {
222                 if (signal_pending(current))
223                         return -EINTR;
224                 if (__put_user(offset, &dirent->d_off))
225                         goto efault;
226         }
227         dirent = buf->current_dir;
228         if (__put_user(d_ino, &dirent->d_ino))
229                 goto efault;
230         if (__put_user(reclen, &dirent->d_reclen))
231                 goto efault;
232         if (copy_to_user(dirent->d_name, name, namlen))
233                 goto efault;
234         if (__put_user(0, dirent->d_name + namlen))
235                 goto efault;
236         if (__put_user(d_type, (char __user *) dirent + reclen - 1))
237                 goto efault;
238         buf->previous = dirent;
239         dirent = (void __user *)dirent + reclen;
240         buf->current_dir = dirent;
241         buf->count -= reclen;
242         return 0;
243 efault:
244         buf->error = -EFAULT;
245         return -EFAULT;
246 }
247
248 SYSCALL_DEFINE3(getdents, unsigned int, fd,
249                 struct linux_dirent __user *, dirent, unsigned int, count)
250 {
251         struct fd f;
252         struct linux_dirent __user * lastdirent;
253         struct getdents_callback buf = {
254                 .ctx.actor = filldir,
255                 .count = count,
256                 .current_dir = dirent
257         };
258         int error;
259
260         if (!access_ok(VERIFY_WRITE, dirent, count))
261                 return -EFAULT;
262
263         f = fdget_pos(fd);
264         if (!f.file)
265                 return -EBADF;
266
267         error = iterate_dir(f.file, &buf.ctx);
268         if (error >= 0)
269                 error = buf.error;
270         lastdirent = buf.previous;
271         if (lastdirent) {
272                 if (put_user(buf.ctx.pos, &lastdirent->d_off))
273                         error = -EFAULT;
274                 else
275                         error = count - buf.count;
276         }
277         fdput_pos(f);
278         return error;
279 }
280
281 struct getdents_callback64 {
282         struct dir_context ctx;
283         struct linux_dirent64 __user * current_dir;
284         struct linux_dirent64 __user * previous;
285         int count;
286         int error;
287 };
288
289 static int filldir64(struct dir_context *ctx, const char *name, int namlen,
290                      loff_t offset, u64 ino, unsigned int d_type)
291 {
292         struct linux_dirent64 __user *dirent;
293         struct getdents_callback64 *buf =
294                 container_of(ctx, struct getdents_callback64, ctx);
295         int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
296                 sizeof(u64));
297
298         buf->error = verify_dirent_name(name, namlen);
299         if (unlikely(buf->error))
300                 return buf->error;
301         buf->error = -EINVAL;   /* only used if we fail.. */
302         if (reclen > buf->count)
303                 return -EINVAL;
304         dirent = buf->previous;
305         if (dirent) {
306                 if (signal_pending(current))
307                         return -EINTR;
308                 if (__put_user(offset, &dirent->d_off))
309                         goto efault;
310         }
311         dirent = buf->current_dir;
312         if (__put_user(ino, &dirent->d_ino))
313                 goto efault;
314         if (__put_user(0, &dirent->d_off))
315                 goto efault;
316         if (__put_user(reclen, &dirent->d_reclen))
317                 goto efault;
318         if (__put_user(d_type, &dirent->d_type))
319                 goto efault;
320         if (copy_to_user(dirent->d_name, name, namlen))
321                 goto efault;
322         if (__put_user(0, dirent->d_name + namlen))
323                 goto efault;
324         buf->previous = dirent;
325         dirent = (void __user *)dirent + reclen;
326         buf->current_dir = dirent;
327         buf->count -= reclen;
328         return 0;
329 efault:
330         buf->error = -EFAULT;
331         return -EFAULT;
332 }
333
334 SYSCALL_DEFINE3(getdents64, unsigned int, fd,
335                 struct linux_dirent64 __user *, dirent, unsigned int, count)
336 {
337         struct fd f;
338         struct linux_dirent64 __user * lastdirent;
339         struct getdents_callback64 buf = {
340                 .ctx.actor = filldir64,
341                 .count = count,
342                 .current_dir = dirent
343         };
344         int error;
345
346         if (!access_ok(VERIFY_WRITE, dirent, count))
347                 return -EFAULT;
348
349         f = fdget_pos(fd);
350         if (!f.file)
351                 return -EBADF;
352
353         error = iterate_dir(f.file, &buf.ctx);
354         if (error >= 0)
355                 error = buf.error;
356         lastdirent = buf.previous;
357         if (lastdirent) {
358                 typeof(lastdirent->d_off) d_off = buf.ctx.pos;
359                 if (__put_user(d_off, &lastdirent->d_off))
360                         error = -EFAULT;
361                 else
362                         error = count - buf.count;
363         }
364         fdput_pos(f);
365         return error;
366 }