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