162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#include <linux/syscalls.h>
362306a36Sopenharmony_ci#include <linux/export.h>
462306a36Sopenharmony_ci#include <linux/uaccess.h>
562306a36Sopenharmony_ci#include <linux/fs_struct.h>
662306a36Sopenharmony_ci#include <linux/fs.h>
762306a36Sopenharmony_ci#include <linux/slab.h>
862306a36Sopenharmony_ci#include <linux/prefetch.h>
962306a36Sopenharmony_ci#include "mount.h"
1062306a36Sopenharmony_ci#include "internal.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct prepend_buffer {
1362306a36Sopenharmony_ci	char *buf;
1462306a36Sopenharmony_ci	int len;
1562306a36Sopenharmony_ci};
1662306a36Sopenharmony_ci#define DECLARE_BUFFER(__name, __buf, __len) \
1762306a36Sopenharmony_ci	struct prepend_buffer __name = {.buf = __buf + __len, .len = __len}
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic char *extract_string(struct prepend_buffer *p)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	if (likely(p->len >= 0))
2262306a36Sopenharmony_ci		return p->buf;
2362306a36Sopenharmony_ci	return ERR_PTR(-ENAMETOOLONG);
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic bool prepend_char(struct prepend_buffer *p, unsigned char c)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	if (likely(p->len > 0)) {
2962306a36Sopenharmony_ci		p->len--;
3062306a36Sopenharmony_ci		*--p->buf = c;
3162306a36Sopenharmony_ci		return true;
3262306a36Sopenharmony_ci	}
3362306a36Sopenharmony_ci	p->len = -1;
3462306a36Sopenharmony_ci	return false;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * The source of the prepend data can be an optimistic load
3962306a36Sopenharmony_ci * of a dentry name and length. And because we don't hold any
4062306a36Sopenharmony_ci * locks, the length and the pointer to the name may not be
4162306a36Sopenharmony_ci * in sync if a concurrent rename happens, and the kernel
4262306a36Sopenharmony_ci * copy might fault as a result.
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci * The end result will correct itself when we check the
4562306a36Sopenharmony_ci * rename sequence count, but we need to be able to handle
4662306a36Sopenharmony_ci * the fault gracefully.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_cistatic bool prepend_copy(void *dst, const void *src, int len)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	if (unlikely(copy_from_kernel_nofault(dst, src, len))) {
5162306a36Sopenharmony_ci		memset(dst, 'x', len);
5262306a36Sopenharmony_ci		return false;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci	return true;
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic bool prepend(struct prepend_buffer *p, const char *str, int namelen)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	// Already overflowed?
6062306a36Sopenharmony_ci	if (p->len < 0)
6162306a36Sopenharmony_ci		return false;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	// Will overflow?
6462306a36Sopenharmony_ci	if (p->len < namelen) {
6562306a36Sopenharmony_ci		// Fill as much as possible from the end of the name
6662306a36Sopenharmony_ci		str += namelen - p->len;
6762306a36Sopenharmony_ci		p->buf -= p->len;
6862306a36Sopenharmony_ci		prepend_copy(p->buf, str, p->len);
6962306a36Sopenharmony_ci		p->len = -1;
7062306a36Sopenharmony_ci		return false;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	// Fits fully
7462306a36Sopenharmony_ci	p->len -= namelen;
7562306a36Sopenharmony_ci	p->buf -= namelen;
7662306a36Sopenharmony_ci	return prepend_copy(p->buf, str, namelen);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/**
8062306a36Sopenharmony_ci * prepend_name - prepend a pathname in front of current buffer pointer
8162306a36Sopenharmony_ci * @p: prepend buffer which contains buffer pointer and allocated length
8262306a36Sopenharmony_ci * @name: name string and length qstr structure
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * With RCU path tracing, it may race with d_move(). Use READ_ONCE() to
8562306a36Sopenharmony_ci * make sure that either the old or the new name pointer and length are
8662306a36Sopenharmony_ci * fetched. However, there may be mismatch between length and pointer.
8762306a36Sopenharmony_ci * But since the length cannot be trusted, we need to copy the name very
8862306a36Sopenharmony_ci * carefully when doing the prepend_copy(). It also prepends "/" at
8962306a36Sopenharmony_ci * the beginning of the name. The sequence number check at the caller will
9062306a36Sopenharmony_ci * retry it again when a d_move() does happen. So any garbage in the buffer
9162306a36Sopenharmony_ci * due to mismatched pointer and length will be discarded.
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci * Load acquire is needed to make sure that we see the new name data even
9462306a36Sopenharmony_ci * if we might get the length wrong.
9562306a36Sopenharmony_ci */
9662306a36Sopenharmony_cistatic bool prepend_name(struct prepend_buffer *p, const struct qstr *name)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	const char *dname = smp_load_acquire(&name->name); /* ^^^ */
9962306a36Sopenharmony_ci	u32 dlen = READ_ONCE(name->len);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return prepend(p, dname, dlen) && prepend_char(p, '/');
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic int __prepend_path(const struct dentry *dentry, const struct mount *mnt,
10562306a36Sopenharmony_ci			  const struct path *root, struct prepend_buffer *p)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	while (dentry != root->dentry || &mnt->mnt != root->mnt) {
10862306a36Sopenharmony_ci		const struct dentry *parent = READ_ONCE(dentry->d_parent);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		if (dentry == mnt->mnt.mnt_root) {
11162306a36Sopenharmony_ci			struct mount *m = READ_ONCE(mnt->mnt_parent);
11262306a36Sopenharmony_ci			struct mnt_namespace *mnt_ns;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci			if (likely(mnt != m)) {
11562306a36Sopenharmony_ci				dentry = READ_ONCE(mnt->mnt_mountpoint);
11662306a36Sopenharmony_ci				mnt = m;
11762306a36Sopenharmony_ci				continue;
11862306a36Sopenharmony_ci			}
11962306a36Sopenharmony_ci			/* Global root */
12062306a36Sopenharmony_ci			mnt_ns = READ_ONCE(mnt->mnt_ns);
12162306a36Sopenharmony_ci			/* open-coded is_mounted() to use local mnt_ns */
12262306a36Sopenharmony_ci			if (!IS_ERR_OR_NULL(mnt_ns) && !is_anon_ns(mnt_ns))
12362306a36Sopenharmony_ci				return 1;	// absolute root
12462306a36Sopenharmony_ci			else
12562306a36Sopenharmony_ci				return 2;	// detached or not attached yet
12662306a36Sopenharmony_ci		}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci		if (unlikely(dentry == parent))
12962306a36Sopenharmony_ci			/* Escaped? */
13062306a36Sopenharmony_ci			return 3;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci		prefetch(parent);
13362306a36Sopenharmony_ci		if (!prepend_name(p, &dentry->d_name))
13462306a36Sopenharmony_ci			break;
13562306a36Sopenharmony_ci		dentry = parent;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci	return 0;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/**
14162306a36Sopenharmony_ci * prepend_path - Prepend path string to a buffer
14262306a36Sopenharmony_ci * @path: the dentry/vfsmount to report
14362306a36Sopenharmony_ci * @root: root vfsmnt/dentry
14462306a36Sopenharmony_ci * @p: prepend buffer which contains buffer pointer and allocated length
14562306a36Sopenharmony_ci *
14662306a36Sopenharmony_ci * The function will first try to write out the pathname without taking any
14762306a36Sopenharmony_ci * lock other than the RCU read lock to make sure that dentries won't go away.
14862306a36Sopenharmony_ci * It only checks the sequence number of the global rename_lock as any change
14962306a36Sopenharmony_ci * in the dentry's d_seq will be preceded by changes in the rename_lock
15062306a36Sopenharmony_ci * sequence number. If the sequence number had been changed, it will restart
15162306a36Sopenharmony_ci * the whole pathname back-tracing sequence again by taking the rename_lock.
15262306a36Sopenharmony_ci * In this case, there is no need to take the RCU read lock as the recursive
15362306a36Sopenharmony_ci * parent pointer references will keep the dentry chain alive as long as no
15462306a36Sopenharmony_ci * rename operation is performed.
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_cistatic int prepend_path(const struct path *path,
15762306a36Sopenharmony_ci			const struct path *root,
15862306a36Sopenharmony_ci			struct prepend_buffer *p)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	unsigned seq, m_seq = 0;
16162306a36Sopenharmony_ci	struct prepend_buffer b;
16262306a36Sopenharmony_ci	int error;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	rcu_read_lock();
16562306a36Sopenharmony_cirestart_mnt:
16662306a36Sopenharmony_ci	read_seqbegin_or_lock(&mount_lock, &m_seq);
16762306a36Sopenharmony_ci	seq = 0;
16862306a36Sopenharmony_ci	rcu_read_lock();
16962306a36Sopenharmony_cirestart:
17062306a36Sopenharmony_ci	b = *p;
17162306a36Sopenharmony_ci	read_seqbegin_or_lock(&rename_lock, &seq);
17262306a36Sopenharmony_ci	error = __prepend_path(path->dentry, real_mount(path->mnt), root, &b);
17362306a36Sopenharmony_ci	if (!(seq & 1))
17462306a36Sopenharmony_ci		rcu_read_unlock();
17562306a36Sopenharmony_ci	if (need_seqretry(&rename_lock, seq)) {
17662306a36Sopenharmony_ci		seq = 1;
17762306a36Sopenharmony_ci		goto restart;
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci	done_seqretry(&rename_lock, seq);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (!(m_seq & 1))
18262306a36Sopenharmony_ci		rcu_read_unlock();
18362306a36Sopenharmony_ci	if (need_seqretry(&mount_lock, m_seq)) {
18462306a36Sopenharmony_ci		m_seq = 1;
18562306a36Sopenharmony_ci		goto restart_mnt;
18662306a36Sopenharmony_ci	}
18762306a36Sopenharmony_ci	done_seqretry(&mount_lock, m_seq);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	if (unlikely(error == 3))
19062306a36Sopenharmony_ci		b = *p;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (b.len == p->len)
19362306a36Sopenharmony_ci		prepend_char(&b, '/');
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	*p = b;
19662306a36Sopenharmony_ci	return error;
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci/**
20062306a36Sopenharmony_ci * __d_path - return the path of a dentry
20162306a36Sopenharmony_ci * @path: the dentry/vfsmount to report
20262306a36Sopenharmony_ci * @root: root vfsmnt/dentry
20362306a36Sopenharmony_ci * @buf: buffer to return value in
20462306a36Sopenharmony_ci * @buflen: buffer length
20562306a36Sopenharmony_ci *
20662306a36Sopenharmony_ci * Convert a dentry into an ASCII path name.
20762306a36Sopenharmony_ci *
20862306a36Sopenharmony_ci * Returns a pointer into the buffer or an error code if the
20962306a36Sopenharmony_ci * path was too long.
21062306a36Sopenharmony_ci *
21162306a36Sopenharmony_ci * "buflen" should be positive.
21262306a36Sopenharmony_ci *
21362306a36Sopenharmony_ci * If the path is not reachable from the supplied root, return %NULL.
21462306a36Sopenharmony_ci */
21562306a36Sopenharmony_cichar *__d_path(const struct path *path,
21662306a36Sopenharmony_ci	       const struct path *root,
21762306a36Sopenharmony_ci	       char *buf, int buflen)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	DECLARE_BUFFER(b, buf, buflen);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	prepend_char(&b, 0);
22262306a36Sopenharmony_ci	if (unlikely(prepend_path(path, root, &b) > 0))
22362306a36Sopenharmony_ci		return NULL;
22462306a36Sopenharmony_ci	return extract_string(&b);
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cichar *d_absolute_path(const struct path *path,
22862306a36Sopenharmony_ci	       char *buf, int buflen)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	struct path root = {};
23162306a36Sopenharmony_ci	DECLARE_BUFFER(b, buf, buflen);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	prepend_char(&b, 0);
23462306a36Sopenharmony_ci	if (unlikely(prepend_path(path, &root, &b) > 1))
23562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
23662306a36Sopenharmony_ci	return extract_string(&b);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	unsigned seq;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	do {
24462306a36Sopenharmony_ci		seq = read_seqcount_begin(&fs->seq);
24562306a36Sopenharmony_ci		*root = fs->root;
24662306a36Sopenharmony_ci	} while (read_seqcount_retry(&fs->seq, seq));
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci/**
25062306a36Sopenharmony_ci * d_path - return the path of a dentry
25162306a36Sopenharmony_ci * @path: path to report
25262306a36Sopenharmony_ci * @buf: buffer to return value in
25362306a36Sopenharmony_ci * @buflen: buffer length
25462306a36Sopenharmony_ci *
25562306a36Sopenharmony_ci * Convert a dentry into an ASCII path name. If the entry has been deleted
25662306a36Sopenharmony_ci * the string " (deleted)" is appended. Note that this is ambiguous.
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci * Returns a pointer into the buffer or an error code if the path was
25962306a36Sopenharmony_ci * too long. Note: Callers should use the returned pointer, not the passed
26062306a36Sopenharmony_ci * in buffer, to use the name! The implementation often starts at an offset
26162306a36Sopenharmony_ci * into the buffer, and may leave 0 bytes at the start.
26262306a36Sopenharmony_ci *
26362306a36Sopenharmony_ci * "buflen" should be positive.
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_cichar *d_path(const struct path *path, char *buf, int buflen)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	DECLARE_BUFFER(b, buf, buflen);
26862306a36Sopenharmony_ci	struct path root;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * We have various synthetic filesystems that never get mounted.  On
27262306a36Sopenharmony_ci	 * these filesystems dentries are never used for lookup purposes, and
27362306a36Sopenharmony_ci	 * thus don't need to be hashed.  They also don't need a name until a
27462306a36Sopenharmony_ci	 * user wants to identify the object in /proc/pid/fd/.  The little hack
27562306a36Sopenharmony_ci	 * below allows us to generate a name for these objects on demand:
27662306a36Sopenharmony_ci	 *
27762306a36Sopenharmony_ci	 * Some pseudo inodes are mountable.  When they are mounted
27862306a36Sopenharmony_ci	 * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
27962306a36Sopenharmony_ci	 * and instead have d_path return the mounted path.
28062306a36Sopenharmony_ci	 */
28162306a36Sopenharmony_ci	if (path->dentry->d_op && path->dentry->d_op->d_dname &&
28262306a36Sopenharmony_ci	    (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
28362306a36Sopenharmony_ci		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	rcu_read_lock();
28662306a36Sopenharmony_ci	get_fs_root_rcu(current->fs, &root);
28762306a36Sopenharmony_ci	if (unlikely(d_unlinked(path->dentry)))
28862306a36Sopenharmony_ci		prepend(&b, " (deleted)", 11);
28962306a36Sopenharmony_ci	else
29062306a36Sopenharmony_ci		prepend_char(&b, 0);
29162306a36Sopenharmony_ci	prepend_path(path, &root, &b);
29262306a36Sopenharmony_ci	rcu_read_unlock();
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	return extract_string(&b);
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ciEXPORT_SYMBOL(d_path);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci/*
29962306a36Sopenharmony_ci * Helper function for dentry_operations.d_dname() members
30062306a36Sopenharmony_ci */
30162306a36Sopenharmony_cichar *dynamic_dname(char *buffer, int buflen, const char *fmt, ...)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	va_list args;
30462306a36Sopenharmony_ci	char temp[64];
30562306a36Sopenharmony_ci	int sz;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	va_start(args, fmt);
30862306a36Sopenharmony_ci	sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
30962306a36Sopenharmony_ci	va_end(args);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	if (sz > sizeof(temp) || sz > buflen)
31262306a36Sopenharmony_ci		return ERR_PTR(-ENAMETOOLONG);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	buffer += buflen - sz;
31562306a36Sopenharmony_ci	return memcpy(buffer, temp, sz);
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cichar *simple_dname(struct dentry *dentry, char *buffer, int buflen)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	DECLARE_BUFFER(b, buffer, buflen);
32162306a36Sopenharmony_ci	/* these dentries are never renamed, so d_lock is not needed */
32262306a36Sopenharmony_ci	prepend(&b, " (deleted)", 11);
32362306a36Sopenharmony_ci	prepend(&b, dentry->d_name.name, dentry->d_name.len);
32462306a36Sopenharmony_ci	prepend_char(&b, '/');
32562306a36Sopenharmony_ci	return extract_string(&b);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/*
32962306a36Sopenharmony_ci * Write full pathname from the root of the filesystem into the buffer.
33062306a36Sopenharmony_ci */
33162306a36Sopenharmony_cistatic char *__dentry_path(const struct dentry *d, struct prepend_buffer *p)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	const struct dentry *dentry;
33462306a36Sopenharmony_ci	struct prepend_buffer b;
33562306a36Sopenharmony_ci	int seq = 0;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	rcu_read_lock();
33862306a36Sopenharmony_cirestart:
33962306a36Sopenharmony_ci	dentry = d;
34062306a36Sopenharmony_ci	b = *p;
34162306a36Sopenharmony_ci	read_seqbegin_or_lock(&rename_lock, &seq);
34262306a36Sopenharmony_ci	while (!IS_ROOT(dentry)) {
34362306a36Sopenharmony_ci		const struct dentry *parent = dentry->d_parent;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		prefetch(parent);
34662306a36Sopenharmony_ci		if (!prepend_name(&b, &dentry->d_name))
34762306a36Sopenharmony_ci			break;
34862306a36Sopenharmony_ci		dentry = parent;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci	if (!(seq & 1))
35162306a36Sopenharmony_ci		rcu_read_unlock();
35262306a36Sopenharmony_ci	if (need_seqretry(&rename_lock, seq)) {
35362306a36Sopenharmony_ci		seq = 1;
35462306a36Sopenharmony_ci		goto restart;
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci	done_seqretry(&rename_lock, seq);
35762306a36Sopenharmony_ci	if (b.len == p->len)
35862306a36Sopenharmony_ci		prepend_char(&b, '/');
35962306a36Sopenharmony_ci	return extract_string(&b);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cichar *dentry_path_raw(const struct dentry *dentry, char *buf, int buflen)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	DECLARE_BUFFER(b, buf, buflen);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	prepend_char(&b, 0);
36762306a36Sopenharmony_ci	return __dentry_path(dentry, &b);
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ciEXPORT_SYMBOL(dentry_path_raw);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cichar *dentry_path(const struct dentry *dentry, char *buf, int buflen)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	DECLARE_BUFFER(b, buf, buflen);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	if (unlikely(d_unlinked(dentry)))
37662306a36Sopenharmony_ci		prepend(&b, "//deleted", 10);
37762306a36Sopenharmony_ci	else
37862306a36Sopenharmony_ci		prepend_char(&b, 0);
37962306a36Sopenharmony_ci	return __dentry_path(dentry, &b);
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_cistatic void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
38362306a36Sopenharmony_ci				    struct path *pwd)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	unsigned seq;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	do {
38862306a36Sopenharmony_ci		seq = read_seqcount_begin(&fs->seq);
38962306a36Sopenharmony_ci		*root = fs->root;
39062306a36Sopenharmony_ci		*pwd = fs->pwd;
39162306a36Sopenharmony_ci	} while (read_seqcount_retry(&fs->seq, seq));
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci/*
39562306a36Sopenharmony_ci * NOTE! The user-level library version returns a
39662306a36Sopenharmony_ci * character pointer. The kernel system call just
39762306a36Sopenharmony_ci * returns the length of the buffer filled (which
39862306a36Sopenharmony_ci * includes the ending '\0' character), or a negative
39962306a36Sopenharmony_ci * error value. So libc would do something like
40062306a36Sopenharmony_ci *
40162306a36Sopenharmony_ci *	char *getcwd(char * buf, size_t size)
40262306a36Sopenharmony_ci *	{
40362306a36Sopenharmony_ci *		int retval;
40462306a36Sopenharmony_ci *
40562306a36Sopenharmony_ci *		retval = sys_getcwd(buf, size);
40662306a36Sopenharmony_ci *		if (retval >= 0)
40762306a36Sopenharmony_ci *			return buf;
40862306a36Sopenharmony_ci *		errno = -retval;
40962306a36Sopenharmony_ci *		return NULL;
41062306a36Sopenharmony_ci *	}
41162306a36Sopenharmony_ci */
41262306a36Sopenharmony_ciSYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	int error;
41562306a36Sopenharmony_ci	struct path pwd, root;
41662306a36Sopenharmony_ci	char *page = __getname();
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (!page)
41962306a36Sopenharmony_ci		return -ENOMEM;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	rcu_read_lock();
42262306a36Sopenharmony_ci	get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	if (unlikely(d_unlinked(pwd.dentry))) {
42562306a36Sopenharmony_ci		rcu_read_unlock();
42662306a36Sopenharmony_ci		error = -ENOENT;
42762306a36Sopenharmony_ci	} else {
42862306a36Sopenharmony_ci		unsigned len;
42962306a36Sopenharmony_ci		DECLARE_BUFFER(b, page, PATH_MAX);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci		prepend_char(&b, 0);
43262306a36Sopenharmony_ci		if (unlikely(prepend_path(&pwd, &root, &b) > 0))
43362306a36Sopenharmony_ci			prepend(&b, "(unreachable)", 13);
43462306a36Sopenharmony_ci		rcu_read_unlock();
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci		len = PATH_MAX - b.len;
43762306a36Sopenharmony_ci		if (unlikely(len > PATH_MAX))
43862306a36Sopenharmony_ci			error = -ENAMETOOLONG;
43962306a36Sopenharmony_ci		else if (unlikely(len > size))
44062306a36Sopenharmony_ci			error = -ERANGE;
44162306a36Sopenharmony_ci		else if (copy_to_user(buf, b.buf, len))
44262306a36Sopenharmony_ci			error = -EFAULT;
44362306a36Sopenharmony_ci		else
44462306a36Sopenharmony_ci			error = len;
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci	__putname(page);
44762306a36Sopenharmony_ci	return error;
44862306a36Sopenharmony_ci}
449