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 inode_lock(inode); 42 // res = mutex_lock_killable(&inode->i_mutex); 43 // if (res) 44 // goto out; 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 * Traditional linux readdir() handling.. 68 * 69 * "count=1" is a special case, meaning that the buffer is one 70 * dirent-structure in size and that the code can't handle more 71 * anyway. Thus the special "fillonedir()" function for that 72 * case (the low-level handlers don't need to care about this). 73 */ 74 75 #ifdef __ARCH_WANT_OLD_READDIR 76 77 struct old_linux_dirent { 78 unsigned long d_ino; 79 unsigned long d_offset; 80 unsigned short d_namlen; 81 char d_name[1]; 82 }; 83 84 struct readdir_callback { 85 struct dir_context ctx; 86 struct old_linux_dirent __user * dirent; 87 int result; 88 }; 89 90 static int fillonedir(struct dir_context *ctx, const char *name, int namlen, 91 loff_t offset, u64 ino, unsigned int d_type) 92 { 93 struct readdir_callback *buf = 94 container_of(ctx, struct readdir_callback, ctx); 95 struct old_linux_dirent __user * dirent; 96 unsigned long d_ino; 97 98 if (buf->result) 99 return -EINVAL; 100 d_ino = ino; 101 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { 102 buf->result = -EOVERFLOW; 103 return -EOVERFLOW; 104 } 105 buf->result++; 106 dirent = buf->dirent; 107 if (!access_ok(VERIFY_WRITE, dirent, 108 (unsigned long)(dirent->d_name + namlen + 1) - 109 (unsigned long)dirent)) 110 goto efault; 111 if ( __put_user(d_ino, &dirent->d_ino) || 112 __put_user(offset, &dirent->d_offset) || 113 __put_user(namlen, &dirent->d_namlen) || 114 __copy_to_user(dirent->d_name, name, namlen) || 115 __put_user(0, dirent->d_name + namlen)) 116 goto efault; 117 return 0; 118 efault: 119 buf->result = -EFAULT; 120 return -EFAULT; 121 } 122 123 SYSCALL_DEFINE3(old_readdir, unsigned int, fd, 124 struct old_linux_dirent __user *, dirent, unsigned int, count) 125 { 126 int error; 127 struct fd f = fdget_pos(fd); 128 struct readdir_callback buf = { 129 .ctx.actor = fillonedir, 130 .dirent = dirent 131 }; 132 133 if (!f.file) 134 return -EBADF; 135 136 error = iterate_dir(f.file, &buf.ctx); 137 if (buf.result) 138 error = buf.result; 139 140 fdput_pos(f); 141 return error; 142 } 143 144 #endif /* __ARCH_WANT_OLD_READDIR */ 145 146 /* 147 * New, all-improved, singing, dancing, iBCS2-compliant getdents() 148 * interface. 149 */ 150 struct linux_dirent { 151 unsigned long d_ino; 152 unsigned long d_off; 153 unsigned short d_reclen; 154 char d_name[1]; 155 }; 156 157 struct getdents_callback { 158 struct dir_context ctx; 159 struct linux_dirent __user * current_dir; 160 struct linux_dirent __user * previous; 161 int count; 162 int error; 163 }; 164 165 static int filldir(struct dir_context *ctx, const char *name, int namlen, 166 loff_t offset, u64 ino, unsigned int d_type) 167 { 168 struct linux_dirent __user * dirent; 169 struct getdents_callback *buf = 170 container_of(ctx, struct getdents_callback, ctx); 171 unsigned long d_ino; 172 int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, 173 sizeof(long)); 174 175 buf->error = -EINVAL; /* only used if we fail.. */ 176 if (reclen > buf->count) 177 return -EINVAL; 178 d_ino = ino; 179 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { 180 buf->error = -EOVERFLOW; 181 return -EOVERFLOW; 182 } 183 dirent = buf->previous; 184 if (dirent) { 185 if (__put_user(offset, &dirent->d_off)) 186 goto efault; 187 } 188 dirent = buf->current_dir; 189 if (__put_user(d_ino, &dirent->d_ino)) 190 goto efault; 191 if (__put_user(reclen, &dirent->d_reclen)) 192 goto efault; 193 if (copy_to_user(dirent->d_name, name, namlen)) 194 goto efault; 195 if (__put_user(0, dirent->d_name + namlen)) 196 goto efault; 197 if (__put_user(d_type, (char __user *) dirent + reclen - 1)) 198 goto efault; 199 buf->previous = dirent; 200 dirent = (void __user *)dirent + reclen; 201 buf->current_dir = dirent; 202 buf->count -= reclen; 203 return 0; 204 efault: 205 buf->error = -EFAULT; 206 return -EFAULT; 207 } 208 209 SYSCALL_DEFINE3(getdents, unsigned int, fd, 210 struct linux_dirent __user *, dirent, unsigned int, count) 211 { 212 struct fd f; 213 struct linux_dirent __user * lastdirent; 214 struct getdents_callback buf = { 215 .ctx.actor = filldir, 216 .count = count, 217 .current_dir = dirent 218 }; 219 int error; 220 221 if (!access_ok(VERIFY_WRITE, dirent, count)) 222 return -EFAULT; 223 224 f = fdget_pos(fd); 225 if (!f.file) 226 return -EBADF; 227 228 error = iterate_dir(f.file, &buf.ctx); 229 if (error >= 0) 230 error = buf.error; 231 lastdirent = buf.previous; 232 if (lastdirent) { 233 if (put_user(buf.ctx.pos, &lastdirent->d_off)) 234 error = -EFAULT; 235 else 236 error = count - buf.count; 237 } 238 fdput_pos(f); 239 return error; 240 } 241 242 struct getdents_callback64 { 243 struct dir_context ctx; 244 struct linux_dirent64 __user * current_dir; 245 struct linux_dirent64 __user * previous; 246 int count; 247 int error; 248 }; 249 250 static int filldir64(struct dir_context *ctx, const char *name, int namlen, 251 loff_t offset, u64 ino, unsigned int d_type) 252 { 253 struct linux_dirent64 __user *dirent; 254 struct getdents_callback64 *buf = 255 container_of(ctx, struct getdents_callback64, ctx); 256 int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, 257 sizeof(u64)); 258 259 buf->error = -EINVAL; /* only used if we fail.. */ 260 if (reclen > buf->count) 261 return -EINVAL; 262 dirent = buf->previous; 263 if (dirent) { 264 if (__put_user(offset, &dirent->d_off)) 265 goto efault; 266 } 267 dirent = buf->current_dir; 268 if (__put_user(ino, &dirent->d_ino)) 269 goto efault; 270 if (__put_user(0, &dirent->d_off)) 271 goto efault; 272 if (__put_user(reclen, &dirent->d_reclen)) 273 goto efault; 274 if (__put_user(d_type, &dirent->d_type)) 275 goto efault; 276 if (copy_to_user(dirent->d_name, name, namlen)) 277 goto efault; 278 if (__put_user(0, dirent->d_name + namlen)) 279 goto efault; 280 buf->previous = dirent; 281 dirent = (void __user *)dirent + reclen; 282 buf->current_dir = dirent; 283 buf->count -= reclen; 284 return 0; 285 efault: 286 buf->error = -EFAULT; 287 return -EFAULT; 288 } 289 290 SYSCALL_DEFINE3(getdents64, unsigned int, fd, 291 struct linux_dirent64 __user *, dirent, unsigned int, count) 292 { 293 struct fd f; 294 struct linux_dirent64 __user * lastdirent; 295 struct getdents_callback64 buf = { 296 .ctx.actor = filldir64, 297 .count = count, 298 .current_dir = dirent 299 }; 300 int error; 301 302 if (!access_ok(VERIFY_WRITE, dirent, count)) 303 return -EFAULT; 304 305 f = fdget_pos(fd); 306 if (!f.file) 307 return -EBADF; 308 309 error = iterate_dir(f.file, &buf.ctx); 310 if (error >= 0) 311 error = buf.error; 312 lastdirent = buf.previous; 313 if (lastdirent) { 314 typeof(lastdirent->d_off) d_off = buf.ctx.pos; 315 if (__put_user(d_off, &lastdirent->d_off)) 316 error = -EFAULT; 317 else 318 error = count - buf.count; 319 } 320 fdput_pos(f); 321 return error; 322 } 323