VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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) }