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