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}
 319EXPORT_SYMBOL(simple_dname);
 320
 321/*
 322 * Write full pathname from the root of the filesystem into the buffer.
 323 */
 324static char *__dentry_path(struct dentry *d, char *buf, int buflen)
 325{
 326        struct dentry *dentry;
 327        char *end, *retval;
 328        int len, seq = 0;
 329        int error = 0;
 330
 331        if (buflen < 2)
 332                goto Elong;
 333
 334        rcu_read_lock();
 335restart:
 336        dentry = d;
 337        end = buf + buflen;
 338        len = buflen;
 339        prepend(&end, &len, "\0", 1);
 340        /* Get '/' right */
 341        retval = end-1;
 342        *retval = '/';
 343        read_seqbegin_or_lock(&rename_lock, &seq);
 344        while (!IS_ROOT(dentry)) {
 345                struct dentry *parent = dentry->d_parent;
 346
 347                prefetch(parent);
 348                error = prepend_name(&end, &len, &dentry->d_name);
 349                if (error)
 350                        break;
 351
 352                retval = end;
 353                dentry = parent;
 354        }
 355        if (!(seq & 1))
 356                rcu_read_unlock();
 357        if (need_seqretry(&rename_lock, seq)) {
 358                seq = 1;
 359                goto restart;
 360        }
 361        done_seqretry(&rename_lock, seq);
 362        if (error)
 363                goto Elong;
 364        return retval;
 365Elong:
 366        return ERR_PTR(-ENAMETOOLONG);
 367}
 368
 369char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
 370{
 371        return __dentry_path(dentry, buf, buflen);
 372}
 373EXPORT_SYMBOL(dentry_path_raw);
 374
 375char *dentry_path(struct dentry *dentry, char *buf, int buflen)
 376{
 377        char *p = NULL;
 378        char *retval;
 379
 380        if (d_unlinked(dentry)) {
 381                p = buf + buflen;
 382                if (prepend(&p, &buflen, "//deleted", 10) != 0)
 383                        goto Elong;
 384                buflen++;
 385        }
 386        retval = __dentry_path(dentry, buf, buflen);
 387        if (!IS_ERR(retval) && p)
 388                *p = '/';       /* restore '/' overriden with '\0' */
 389        return retval;
 390Elong:
 391        return ERR_PTR(-ENAMETOOLONG);
 392}
 393
 394static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
 395                                    struct path *pwd)
 396{
 397        unsigned seq;
 398
 399        do {
 400                seq = read_seqcount_begin(&fs->seq);
 401                *root = fs->root;
 402                *pwd = fs->pwd;
 403        } while (read_seqcount_retry(&fs->seq, seq));
 404}
 405
 406/*
 407 * NOTE! The user-level library version returns a
 408 * character pointer. The kernel system call just
 409 * returns the length of the buffer filled (which
 410 * includes the ending '\0' character), or a negative
 411 * error value. So libc would do something like
 412 *
 413 *      char *getcwd(char * buf, size_t size)
 414 *      {
 415 *              int retval;
 416 *
 417 *              retval = sys_getcwd(buf, size);
 418 *              if (retval >= 0)
 419 *                      return buf;
 420 *              errno = -retval;
 421 *              return NULL;
 422 *      }
 423 */
 424SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 425{
 426        int error;
 427        struct path pwd, root;
 428        char *page = __getname();
 429
 430        if (!page)
 431                return -ENOMEM;
 432
 433        rcu_read_lock();
 434        get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);
 435
 436        error = -ENOENT;
 437        if (!d_unlinked(pwd.dentry)) {
 438                unsigned long len;
 439                char *cwd = page + PATH_MAX;
 440                int buflen = PATH_MAX;
 441
 442                prepend(&cwd, &buflen, "\0", 1);
 443                error = prepend_path(&pwd, &root, &cwd, &buflen);
 444                rcu_read_unlock();
 445
 446                if (error < 0)
 447                        goto out;
 448
 449                /* Unreachable from current root */
 450                if (error > 0) {
 451                        error = prepend_unreachable(&cwd, &buflen);
 452                        if (error)
 453                                goto out;
 454                }
 455
 456                error = -ERANGE;
 457                len = PATH_MAX + page - cwd;
 458                if (len <= size) {
 459                        error = len;
 460                        if (copy_to_user(buf, cwd, len))
 461                                error = -EFAULT;
 462                }
 463        } else {
 464                rcu_read_unlock();
 465        }
 466
 467out:
 468        __putname(page);
 469        return error;
 470}
 471