linux/fs/d_path.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#include <linux/syscalls.h>
   3#include <linux/export.h>
   4#include <linux/uaccess.h>
   5#include <linux/fs_struct.h>
   6#include <linux/fs.h>
   7#include <linux/slab.h>
   8#include <linux/prefetch.h>
   9#include "mount.h"
  10
  11static int prepend(char **buffer, int *buflen, const char *str, int namelen)
  12{
  13        *buflen -= namelen;
  14        if (*buflen < 0)
  15                return -ENAMETOOLONG;
  16        *buffer -= namelen;
  17        memcpy(*buffer, str, namelen);
  18        return 0;
  19}
  20
  21/**
  22 * prepend_name - prepend a pathname in front of current buffer pointer
  23 * @buffer: buffer pointer
  24 * @buflen: allocated length of the buffer
  25 * @name:   name string and length qstr structure
  26 *
  27 * With RCU path tracing, it may race with d_move(). Use READ_ONCE() to
  28 * make sure that either the old or the new name pointer and length are
  29 * fetched. However, there may be mismatch between length and pointer.
  30 * The length cannot be trusted, we need to copy it byte-by-byte until
  31 * the length is reached or a null byte is found. It also prepends "/" at
  32 * the beginning of the name. The sequence number check at the caller will
  33 * retry it again when a d_move() does happen. So any garbage in the buffer
  34 * due to mismatched pointer and length will be discarded.
  35 *
  36 * Load acquire is needed to make sure that we see that terminating NUL.
  37 */
  38static int prepend_name(char **buffer, int *buflen, const struct qstr *name)
  39{
  40        const char *dname = smp_load_acquire(&name->name); /* ^^^ */
  41        u32 dlen = READ_ONCE(name->len);
  42        char *p;
  43
  44        *buflen -= dlen + 1;
  45        if (*buflen < 0)
  46                return -ENAMETOOLONG;
  47        p = *buffer -= dlen + 1;
  48        *p++ = '/';
  49        while (dlen--) {
  50                char c = *dname++;
  51                if (!c)
  52                        break;
  53                *p++ = c;
  54        }
  55        return 0;
  56}
  57
  58/**
  59 * prepend_path - Prepend path string to a buffer
  60 * @path: the dentry/vfsmount to report
  61 * @root: root vfsmnt/dentry
  62 * @buffer: pointer to the end of the buffer
  63 * @buflen: pointer to buffer length
  64 *
  65 * The function will first try to write out the pathname without taking any
  66 * lock other than the RCU read lock to make sure that dentries won't go away.
  67 * It only checks the sequence number of the global rename_lock as any change
  68 * in the dentry's d_seq will be preceded by changes in the rename_lock
  69 * sequence number. If the sequence number had been changed, it will restart
  70 * the whole pathname back-tracing sequence again by taking the rename_lock.
  71 * In this case, there is no need to take the RCU read lock as the recursive
  72 * parent pointer references will keep the dentry chain alive as long as no
  73 * rename operation is performed.
  74 */
  75static int prepend_path(const struct path *path,
  76                        const struct path *root,
  77                        char **buffer, int *buflen)
  78{
  79        struct dentry *dentry;
  80        struct vfsmount *vfsmnt;
  81        struct mount *mnt;
  82        int error = 0;
  83        unsigned seq, m_seq = 0;
  84        char *bptr;
  85        int blen;
  86
  87        rcu_read_lock();
  88restart_mnt:
  89        read_seqbegin_or_lock(&mount_lock, &m_seq);
  90        seq = 0;
  91        rcu_read_lock();
  92restart:
  93        bptr = *buffer;
  94        blen = *buflen;
  95        error = 0;
  96        dentry = path->dentry;
  97        vfsmnt = path->mnt;
  98        mnt = real_mount(vfsmnt);
  99        read_seqbegin_or_lock(&rename_lock, &seq);
 100        while (dentry != root->dentry || vfsmnt != root->mnt) {
 101                struct dentry * parent;
 102
 103                if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
 104                        struct mount *parent = READ_ONCE(mnt->mnt_parent);
 105                        /* Escaped? */
 106                        if (dentry != vfsmnt->mnt_root) {
 107                                bptr = *buffer;
 108                                blen = *buflen;
 109                                error = 3;
 110                                break;
 111                        }
 112                        /* Global root? */
 113                        if (mnt != parent) {
 114                                dentry = READ_ONCE(mnt->mnt_mountpoint);
 115                                mnt = parent;
 116                                vfsmnt = &mnt->mnt;
 117                                continue;
 118                        }
 119                        if (!error)
 120                                error = is_mounted(vfsmnt) ? 1 : 2;
 121                        break;
 122                }
 123                parent = dentry->d_parent;
 124                prefetch(parent);
 125                error = prepend_name(&bptr, &blen, &dentry->d_name);
 126                if (error)
 127                        break;
 128
 129                dentry = parent;
 130        }
 131        if (!(seq & 1))
 132                rcu_read_unlock();
 133        if (need_seqretry(&rename_lock, seq)) {
 134                seq = 1;
 135                goto restart;
 136        }
 137        done_seqretry(&rename_lock, seq);
 138
 139        if (!(m_seq & 1))
 140                rcu_read_unlock();
 141        if (need_seqretry(&mount_lock, m_seq)) {
 142                m_seq = 1;
 143                goto restart_mnt;
 144        }
 145        done_seqretry(&mount_lock, m_seq);
 146
 147        if (error >= 0 && bptr == *buffer) {
 148                if (--blen < 0)
 149                        error = -ENAMETOOLONG;
 150                else
 151                        *--bptr = '/';
 152        }
 153        *buffer = bptr;
 154        *buflen = blen;
 155        return error;
 156}
 157
 158/**
 159 * __d_path - return the path of a dentry
 160 * @path: the dentry/vfsmount to report
 161 * @root: root vfsmnt/dentry
 162 * @buf: buffer to return value in
 163 * @buflen: buffer length
 164 *
 165 * Convert a dentry into an ASCII path name.
 166 *
 167 * Returns a pointer into the buffer or an error code if the
 168 * path was too long.
 169 *
 170 * "buflen" should be positive.
 171 *
 172 * If the path is not reachable from the supplied root, return %NULL.
 173 */
 174char *__d_path(const struct path *path,
 175               const struct path *root,
 176               char *buf, int buflen)
 177{
 178        char *res = buf + buflen;
 179        int error;
 180
 181        prepend(&res, &buflen, "\0", 1);
 182        error = prepend_path(path, root, &res, &buflen);
 183
 184        if (error < 0)
 185                return ERR_PTR(error);
 186        if (error > 0)
 187                return NULL;
 188        return res;
 189}
 190
 191char *d_absolute_path(const struct path *path,
 192               char *buf, int buflen)
 193{
 194        struct path root = {};
 195        char *res = buf + buflen;
 196        int error;
 197
 198        prepend(&res, &buflen, "\0", 1);
 199        error = prepend_path(path, &root, &res, &buflen);
 200
 201        if (error > 1)
 202                error = -EINVAL;
 203        if (error < 0)
 204                return ERR_PTR(error);
 205        return res;
 206}
 207
 208/*
 209 * same as __d_path but appends "(deleted)" for unlinked files.
 210 */
 211static int path_with_deleted(const struct path *path,
 212                             const struct path *root,
 213                             char **buf, int *buflen)
 214{
 215        prepend(buf, buflen, "\0", 1);
 216        if (d_unlinked(path->dentry)) {
 217                int error = prepend(buf, buflen, " (deleted)", 10);
 218                if (error)
 219                        return error;
 220        }
 221
 222        return prepend_path(path, root, buf, buflen);
 223}
 224
 225static int prepend_unreachable(char **buffer, int *buflen)
 226{
 227        return prepend(buffer, buflen, "(unreachable)", 13);
 228}
 229
 230static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
 231{
 232        unsigned seq;
 233
 234        do {
 235                seq = read_seqcount_begin(&fs->seq);
 236                *root = fs->root;
 237        } while (read_seqcount_retry(&fs->seq, seq));
 238}
 239
 240/**
 241 * d_path - return the path of a dentry
 242 * @path: path to report
 243 * @buf: buffer to return value in
 244 * @buflen: buffer length
 245 *
 246 * Convert a dentry into an ASCII path name. If the entry has been deleted
 247 * the string " (deleted)" is appended. Note that this is ambiguous.
 248 *
 249 * Returns a pointer into the buffer or an error code if the path was
 250 * too long. Note: Callers should use the returned pointer, not the passed
 251 * in buffer, to use the name! The implementation often starts at an offset
 252 * into the buffer, and may leave 0 bytes at the start.
 253 *
 254 * "buflen" should be positive.
 255 */
 256char *d_path(const struct path *path, char *buf, int buflen)
 257{
 258        char *res = buf + buflen;
 259        struct path root;
 260        int error;
 261
 262        /*
 263         * We have various synthetic filesystems that never get mounted.  On
 264         * these filesystems dentries are never used for lookup purposes, and
 265         * thus don't need to be hashed.  They also don't need a name until a
 266         * user wants to identify the object in /proc/pid/fd/.  The little hack
 267         * below allows us to generate a name for these objects on demand:
 268         *
 269         * Some pseudo inodes are mountable.  When they are mounted
 270         * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
 271         * and instead have d_path return the mounted path.
 272         */
 273        if (path->dentry->d_op && path->dentry->d_op->d_dname &&
 274            (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
 275                return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 276
 277        rcu_read_lock();
 278        get_fs_root_rcu(current->fs, &root);
 279        error = path_with_deleted(path, &root, &res, &buflen);
 280        rcu_read_unlock();
 281
 282        if (error < 0)
 283                res = ERR_PTR(error);
 284        return res;
 285}
 286EXPORT_SYMBOL(d_path);
 287
 288/*
 289 * Helper function for dentry_operations.d_dname() members
 290 */
 291char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
 292                        const char *fmt, ...)
 293{
 294        va_list args;
 295        char temp[64];
 296        int sz;
 297
 298        va_start(args, fmt);
 299        sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
 300        va_end(args);
 301
 302        if (sz > sizeof(temp) || sz > buflen)
 303                return ERR_PTR(-ENAMETOOLONG);
 304
 305        buffer += buflen - sz;
 306        return memcpy(buffer, temp, sz);
 307}
 308
 309char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
 310{
 311        char *end = buffer + buflen;
 312        /* these dentries are never renamed, so d_lock is not needed */
 313        if (prepend(&end, &buflen, " (deleted)", 11) ||
 314            prepend(&end, &buflen, dentry->d_name.name, dentry->d_name.len) ||
 315            prepend(&end, &buflen, "/", 1))  
 316                end = ERR_PTR(-ENAMETOOLONG);
 317        return end;
 318}
 319
 320/*
 321 * Write full pathname from the root of the filesystem into the buffer.
 322 */
 323static char *__dentry_path(struct dentry *d, char *buf, int buflen)
 324{
 325        struct dentry *dentry;
 326        char *end, *retval;
 327        int len, seq = 0;
 328        int error = 0;
 329
 330        if (buflen < 2)
 331                goto Elong;
 332
 333        rcu_read_lock();
 334restart:
 335        dentry = d;
 336        end = buf + buflen;
 337        len = buflen;
 338        prepend(&end, &len, "\0", 1);
 339        /* Get '/' right */
 340        retval = end-1;
 341        *retval = '/';
 342        read_seqbegin_or_lock(&rename_lock, &seq);
 343        while (!IS_ROOT(dentry)) {
 344                struct dentry *parent = dentry->d_parent;
 345
 346                prefetch(parent);
 347                error = prepend_name(&end, &len, &dentry->d_name);
 348                if (error)
 349                        break;
 350
 351                retval = end;
 352                dentry = parent;
 353        }
 354        if (!(seq & 1))
 355                rcu_read_unlock();
 356        if (need_seqretry(&rename_lock, seq)) {
 357                seq = 1;
 358                goto restart;
 359        }
 360        done_seqretry(&rename_lock, seq);
 361        if (error)
 362                goto Elong;
 363        return retval;
 364Elong:
 365        return ERR_PTR(-ENAMETOOLONG);
 366}
 367
 368char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
 369{
 370        return __dentry_path(dentry, buf, buflen);
 371}
 372EXPORT_SYMBOL(dentry_path_raw);
 373
 374char *dentry_path(struct dentry *dentry, char *buf, int buflen)
 375{
 376        char *p = NULL;
 377        char *retval;
 378
 379        if (d_unlinked(dentry)) {
 380                p = buf + buflen;
 381                if (prepend(&p, &buflen, "//deleted", 10) != 0)
 382                        goto Elong;
 383                buflen++;
 384        }
 385        retval = __dentry_path(dentry, buf, buflen);
 386        if (!IS_ERR(retval) && p)
 387                *p = '/';       /* restore '/' overriden with '\0' */
 388        return retval;
 389Elong:
 390        return ERR_PTR(-ENAMETOOLONG);
 391}
 392
 393static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
 394                                    struct path *pwd)
 395{
 396        unsigned seq;
 397
 398        do {
 399                seq = read_seqcount_begin(&fs->seq);
 400                *root = fs->root;
 401                *pwd = fs->pwd;
 402        } while (read_seqcount_retry(&fs->seq, seq));
 403}
 404
 405/*
 406 * NOTE! The user-level library version returns a
 407 * character pointer. The kernel system call just
 408 * returns the length of the buffer filled (which
 409 * includes the ending '\0' character), or a negative
 410 * error value. So libc would do something like
 411 *
 412 *      char *getcwd(char * buf, size_t size)
 413 *      {
 414 *              int retval;
 415 *
 416 *              retval = sys_getcwd(buf, size);
 417 *              if (retval >= 0)
 418 *                      return buf;
 419 *              errno = -retval;
 420 *              return NULL;
 421 *      }
 422 */
 423SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 424{
 425        int error;
 426        struct path pwd, root;
 427        char *page = __getname();
 428
 429        if (!page)
 430                return -ENOMEM;
 431
 432        rcu_read_lock();
 433        get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);
 434
 435        error = -ENOENT;
 436        if (!d_unlinked(pwd.dentry)) {
 437                unsigned long len;
 438                char *cwd = page + PATH_MAX;
 439                int buflen = PATH_MAX;
 440
 441                prepend(&cwd, &buflen, "\0", 1);
 442                error = prepend_path(&pwd, &root, &cwd, &buflen);
 443                rcu_read_unlock();
 444
 445                if (error < 0)
 446                        goto out;
 447
 448                /* Unreachable from current root */
 449                if (error > 0) {
 450                        error = prepend_unreachable(&cwd, &buflen);
 451                        if (error)
 452                                goto out;
 453                }
 454
 455                error = -ERANGE;
 456                len = PATH_MAX + page - cwd;
 457                if (len <= size) {
 458                        error = len;
 459                        if (copy_to_user(buf, cwd, len))
 460                                error = -EFAULT;
 461                }
 462        } else {
 463                rcu_read_unlock();
 464        }
 465
 466out:
 467        __putname(page);
 468        return error;
 469}
 470