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