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                        struct mnt_namespace *mnt_ns;
 106
 107                        /* Escaped? */
 108                        if (dentry != vfsmnt->mnt_root) {
 109                                bptr = *buffer;
 110                                blen = *buflen;
 111                                error = 3;
 112                                break;
 113                        }
 114                        /* Global root? */
 115                        if (mnt != parent) {
 116                                dentry = READ_ONCE(mnt->mnt_mountpoint);
 117                                mnt = parent;
 118                                vfsmnt = &mnt->mnt;
 119                                continue;
 120                        }
 121                        mnt_ns = READ_ONCE(mnt->mnt_ns);
 122                        /* open-coded is_mounted() to use local mnt_ns */
 123                        if (!IS_ERR_OR_NULL(mnt_ns) && !is_anon_ns(mnt_ns))
 124                                error = 1;      // absolute root
 125                        else
 126                                error = 2;      // detached or not attached yet
 127                        break;
 128                }
 129                parent = dentry->d_parent;
 130                prefetch(parent);
 131                error = prepend_name(&bptr, &blen, &dentry->d_name);
 132                if (error)
 133                        break;
 134
 135                dentry = parent;
 136        }
 137        if (!(seq & 1))
 138                rcu_read_unlock();
 139        if (need_seqretry(&rename_lock, seq)) {
 140                seq = 1;
 141                goto restart;
 142        }
 143        done_seqretry(&rename_lock, seq);
 144
 145        if (!(m_seq & 1))
 146                rcu_read_unlock();
 147        if (need_seqretry(&mount_lock, m_seq)) {
 148                m_seq = 1;
 149                goto restart_mnt;
 150        }
 151        done_seqretry(&mount_lock, m_seq);
 152
 153        if (error >= 0 && bptr == *buffer) {
 154                if (--blen < 0)
 155                        error = -ENAMETOOLONG;
 156                else
 157                        *--bptr = '/';
 158        }
 159        *buffer = bptr;
 160        *buflen = blen;
 161        return error;
 162}
 163
 164/**
 165 * __d_path - return the path of a dentry
 166 * @path: the dentry/vfsmount to report
 167 * @root: root vfsmnt/dentry
 168 * @buf: buffer to return value in
 169 * @buflen: buffer length
 170 *
 171 * Convert a dentry into an ASCII path name.
 172 *
 173 * Returns a pointer into the buffer or an error code if the
 174 * path was too long.
 175 *
 176 * "buflen" should be positive.
 177 *
 178 * If the path is not reachable from the supplied root, return %NULL.
 179 */
 180char *__d_path(const struct path *path,
 181               const struct path *root,
 182               char *buf, int buflen)
 183{
 184        char *res = buf + buflen;
 185        int error;
 186
 187        prepend(&res, &buflen, "\0", 1);
 188        error = prepend_path(path, root, &res, &buflen);
 189
 190        if (error < 0)
 191                return ERR_PTR(error);
 192        if (error > 0)
 193                return NULL;
 194        return res;
 195}
 196
 197char *d_absolute_path(const struct path *path,
 198               char *buf, int buflen)
 199{
 200        struct path root = {};
 201        char *res = buf + buflen;
 202        int error;
 203
 204        prepend(&res, &buflen, "\0", 1);
 205        error = prepend_path(path, &root, &res, &buflen);
 206
 207        if (error > 1)
 208                error = -EINVAL;
 209        if (error < 0)
 210                return ERR_PTR(error);
 211        return res;
 212}
 213
 214/*
 215 * same as __d_path but appends "(deleted)" for unlinked files.
 216 */
 217static int path_with_deleted(const struct path *path,
 218                             const struct path *root,
 219                             char **buf, int *buflen)
 220{
 221        prepend(buf, buflen, "\0", 1);
 222        if (d_unlinked(path->dentry)) {
 223                int error = prepend(buf, buflen, " (deleted)", 10);
 224                if (error)
 225                        return error;
 226        }
 227
 228        return prepend_path(path, root, buf, buflen);
 229}
 230
 231static int prepend_unreachable(char **buffer, int *buflen)
 232{
 233        return prepend(buffer, buflen, "(unreachable)", 13);
 234}
 235
 236static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
 237{
 238        unsigned seq;
 239
 240        do {
 241                seq = read_seqcount_begin(&fs->seq);
 242                *root = fs->root;
 243        } while (read_seqcount_retry(&fs->seq, seq));
 244}
 245
 246/**
 247 * d_path - return the path of a dentry
 248 * @path: path to report
 249 * @buf: buffer to return value in
 250 * @buflen: buffer length
 251 *
 252 * Convert a dentry into an ASCII path name. If the entry has been deleted
 253 * the string " (deleted)" is appended. Note that this is ambiguous.
 254 *
 255 * Returns a pointer into the buffer or an error code if the path was
 256 * too long. Note: Callers should use the returned pointer, not the passed
 257 * in buffer, to use the name! The implementation often starts at an offset
 258 * into the buffer, and may leave 0 bytes at the start.
 259 *
 260 * "buflen" should be positive.
 261 */
 262char *d_path(const struct path *path, char *buf, int buflen)
 263{
 264        char *res = buf + buflen;
 265        struct path root;
 266        int error;
 267
 268        /*
 269         * We have various synthetic filesystems that never get mounted.  On
 270         * these filesystems dentries are never used for lookup purposes, and
 271         * thus don't need to be hashed.  They also don't need a name until a
 272         * user wants to identify the object in /proc/pid/fd/.  The little hack
 273         * below allows us to generate a name for these objects on demand:
 274         *
 275         * Some pseudo inodes are mountable.  When they are mounted
 276         * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
 277         * and instead have d_path return the mounted path.
 278         */
 279        if (path->dentry->d_op && path->dentry->d_op->d_dname &&
 280            (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
 281                return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 282
 283        rcu_read_lock();
 284        get_fs_root_rcu(current->fs, &root);
 285        error = path_with_deleted(path, &root, &res, &buflen);
 286        rcu_read_unlock();
 287
 288        if (error < 0)
 289                res = ERR_PTR(error);
 290        return res;
 291}
 292EXPORT_SYMBOL(d_path);
 293
 294/*
 295 * Helper function for dentry_operations.d_dname() members
 296 */
 297char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
 298                        const char *fmt, ...)
 299{
 300        va_list args;
 301        char temp[64];
 302        int sz;
 303
 304        va_start(args, fmt);
 305        sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
 306        va_end(args);
 307
 308        if (sz > sizeof(temp) || sz > buflen)
 309                return ERR_PTR(-ENAMETOOLONG);
 310
 311        buffer += buflen - sz;
 312        return memcpy(buffer, temp, sz);
 313}
 314
 315char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
 316{
 317        char *end = buffer + buflen;
 318        /* these dentries are never renamed, so d_lock is not needed */
 319        if (prepend(&end, &buflen, " (deleted)", 11) ||
 320            prepend(&end, &buflen, dentry->d_name.name, dentry->d_name.len) ||
 321            prepend(&end, &buflen, "/", 1))  
 322                end = ERR_PTR(-ENAMETOOLONG);
 323        return end;
 324}
 325
 326/*
 327 * Write full pathname from the root of the filesystem into the buffer.
 328 */
 329static char *__dentry_path(struct dentry *d, char *buf, int buflen)
 330{
 331        struct dentry *dentry;
 332        char *end, *retval;
 333        int len, seq = 0;
 334        int error = 0;
 335
 336        if (buflen < 2)
 337                goto Elong;
 338
 339        rcu_read_lock();
 340restart:
 341        dentry = d;
 342        end = buf + buflen;
 343        len = buflen;
 344        prepend(&end, &len, "\0", 1);
 345        /* Get '/' right */
 346        retval = end-1;
 347        *retval = '/';
 348        read_seqbegin_or_lock(&rename_lock, &seq);
 349        while (!IS_ROOT(dentry)) {
 350                struct dentry *parent = dentry->d_parent;
 351
 352                prefetch(parent);
 353                error = prepend_name(&end, &len, &dentry->d_name);
 354                if (error)
 355                        break;
 356
 357                retval = end;
 358                dentry = parent;
 359        }
 360        if (!(seq & 1))
 361                rcu_read_unlock();
 362        if (need_seqretry(&rename_lock, seq)) {
 363                seq = 1;
 364                goto restart;
 365        }
 366        done_seqretry(&rename_lock, seq);
 367        if (error)
 368                goto Elong;
 369        return retval;
 370Elong:
 371        return ERR_PTR(-ENAMETOOLONG);
 372}
 373
 374char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
 375{
 376        return __dentry_path(dentry, buf, buflen);
 377}
 378EXPORT_SYMBOL(dentry_path_raw);
 379
 380char *dentry_path(struct dentry *dentry, char *buf, int buflen)
 381{
 382        char *p = NULL;
 383        char *retval;
 384
 385        if (d_unlinked(dentry)) {
 386                p = buf + buflen;
 387                if (prepend(&p, &buflen, "//deleted", 10) != 0)
 388                        goto Elong;
 389                buflen++;
 390        }
 391        retval = __dentry_path(dentry, buf, buflen);
 392        if (!IS_ERR(retval) && p)
 393                *p = '/';       /* restore '/' overriden with '\0' */
 394        return retval;
 395Elong:
 396        return ERR_PTR(-ENAMETOOLONG);
 397}
 398
 399static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
 400                                    struct path *pwd)
 401{
 402        unsigned seq;
 403
 404        do {
 405                seq = read_seqcount_begin(&fs->seq);
 406                *root = fs->root;
 407                *pwd = fs->pwd;
 408        } while (read_seqcount_retry(&fs->seq, seq));
 409}
 410
 411/*
 412 * NOTE! The user-level library version returns a
 413 * character pointer. The kernel system call just
 414 * returns the length of the buffer filled (which
 415 * includes the ending '\0' character), or a negative
 416 * error value. So libc would do something like
 417 *
 418 *      char *getcwd(char * buf, size_t size)
 419 *      {
 420 *              int retval;
 421 *
 422 *              retval = sys_getcwd(buf, size);
 423 *              if (retval >= 0)
 424 *                      return buf;
 425 *              errno = -retval;
 426 *              return NULL;
 427 *      }
 428 */
 429SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 430{
 431        int error;
 432        struct path pwd, root;
 433        char *page = __getname();
 434
 435        if (!page)
 436                return -ENOMEM;
 437
 438        rcu_read_lock();
 439        get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);
 440
 441        error = -ENOENT;
 442        if (!d_unlinked(pwd.dentry)) {
 443                unsigned long len;
 444                char *cwd = page + PATH_MAX;
 445                int buflen = PATH_MAX;
 446
 447                prepend(&cwd, &buflen, "\0", 1);
 448                error = prepend_path(&pwd, &root, &cwd, &buflen);
 449                rcu_read_unlock();
 450
 451                if (error < 0)
 452                        goto out;
 453
 454                /* Unreachable from current root */
 455                if (error > 0) {
 456                        error = prepend_unreachable(&cwd, &buflen);
 457                        if (error)
 458                                goto out;
 459                }
 460
 461                error = -ERANGE;
 462                len = PATH_MAX + page - cwd;
 463                if (len <= size) {
 464                        error = len;
 465                        if (copy_to_user(buf, cwd, len))
 466                                error = -EFAULT;
 467                }
 468        } else {
 469                rcu_read_unlock();
 470        }
 471
 472out:
 473        __putname(page);
 474        return error;
 475}
 476