449 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#include <linux/syscalls.h>3#include <linux/export.h>4#include <linux/uaccess.h>5#include <linux/fs_struct.h>6#include <linux/fs.h>7#include <linux/slab.h>8#include <linux/prefetch.h>9#include "mount.h"10#include "internal.h"11 12struct prepend_buffer {13 char *buf;14 int len;15};16#define DECLARE_BUFFER(__name, __buf, __len) \17 struct prepend_buffer __name = {.buf = __buf + __len, .len = __len}18 19static char *extract_string(struct prepend_buffer *p)20{21 if (likely(p->len >= 0))22 return p->buf;23 return ERR_PTR(-ENAMETOOLONG);24}25 26static bool prepend_char(struct prepend_buffer *p, unsigned char c)27{28 if (likely(p->len > 0)) {29 p->len--;30 *--p->buf = c;31 return true;32 }33 p->len = -1;34 return false;35}36 37/*38 * The source of the prepend data can be an optimistic load39 * of a dentry name and length. And because we don't hold any40 * locks, the length and the pointer to the name may not be41 * in sync if a concurrent rename happens, and the kernel42 * copy might fault as a result.43 *44 * The end result will correct itself when we check the45 * rename sequence count, but we need to be able to handle46 * the fault gracefully.47 */48static bool prepend_copy(void *dst, const void *src, int len)49{50 if (unlikely(copy_from_kernel_nofault(dst, src, len))) {51 memset(dst, 'x', len);52 return false;53 }54 return true;55}56 57static bool prepend(struct prepend_buffer *p, const char *str, int namelen)58{59 // Already overflowed?60 if (p->len < 0)61 return false;62 63 // Will overflow?64 if (p->len < namelen) {65 // Fill as much as possible from the end of the name66 str += namelen - p->len;67 p->buf -= p->len;68 prepend_copy(p->buf, str, p->len);69 p->len = -1;70 return false;71 }72 73 // Fits fully74 p->len -= namelen;75 p->buf -= namelen;76 return prepend_copy(p->buf, str, namelen);77}78 79/**80 * prepend_name - prepend a pathname in front of current buffer pointer81 * @p: prepend buffer which contains buffer pointer and allocated length82 * @name: name string and length qstr structure83 *84 * With RCU path tracing, it may race with d_move(). Use READ_ONCE() to85 * make sure that either the old or the new name pointer and length are86 * fetched. However, there may be mismatch between length and pointer.87 * But since the length cannot be trusted, we need to copy the name very88 * carefully when doing the prepend_copy(). It also prepends "/" at89 * the beginning of the name. The sequence number check at the caller will90 * retry it again when a d_move() does happen. So any garbage in the buffer91 * due to mismatched pointer and length will be discarded.92 *93 * Load acquire is needed to make sure that we see the new name data even94 * if we might get the length wrong.95 */96static bool prepend_name(struct prepend_buffer *p, const struct qstr *name)97{98 const char *dname = smp_load_acquire(&name->name); /* ^^^ */99 u32 dlen = READ_ONCE(name->len);100 101 return prepend(p, dname, dlen) && prepend_char(p, '/');102}103 104static int __prepend_path(const struct dentry *dentry, const struct mount *mnt,105 const struct path *root, struct prepend_buffer *p)106{107 while (dentry != root->dentry || &mnt->mnt != root->mnt) {108 const struct dentry *parent = READ_ONCE(dentry->d_parent);109 110 if (dentry == mnt->mnt.mnt_root) {111 struct mount *m = READ_ONCE(mnt->mnt_parent);112 struct mnt_namespace *mnt_ns;113 114 if (likely(mnt != m)) {115 dentry = READ_ONCE(mnt->mnt_mountpoint);116 mnt = m;117 continue;118 }119 /* Global root */120 mnt_ns = READ_ONCE(mnt->mnt_ns);121 /* open-coded is_mounted() to use local mnt_ns */122 if (!IS_ERR_OR_NULL(mnt_ns) && !is_anon_ns(mnt_ns))123 return 1; // absolute root124 else125 return 2; // detached or not attached yet126 }127 128 if (unlikely(dentry == parent))129 /* Escaped? */130 return 3;131 132 prefetch(parent);133 if (!prepend_name(p, &dentry->d_name))134 break;135 dentry = parent;136 }137 return 0;138}139 140/**141 * prepend_path - Prepend path string to a buffer142 * @path: the dentry/vfsmount to report143 * @root: root vfsmnt/dentry144 * @p: prepend buffer which contains buffer pointer and allocated length145 *146 * The function will first try to write out the pathname without taking any147 * lock other than the RCU read lock to make sure that dentries won't go away.148 * It only checks the sequence number of the global rename_lock as any change149 * in the dentry's d_seq will be preceded by changes in the rename_lock150 * sequence number. If the sequence number had been changed, it will restart151 * the whole pathname back-tracing sequence again by taking the rename_lock.152 * In this case, there is no need to take the RCU read lock as the recursive153 * parent pointer references will keep the dentry chain alive as long as no154 * rename operation is performed.155 */156static int prepend_path(const struct path *path,157 const struct path *root,158 struct prepend_buffer *p)159{160 unsigned seq, m_seq = 0;161 struct prepend_buffer b;162 int error;163 164 rcu_read_lock();165restart_mnt:166 read_seqbegin_or_lock(&mount_lock, &m_seq);167 seq = 0;168 rcu_read_lock();169restart:170 b = *p;171 read_seqbegin_or_lock(&rename_lock, &seq);172 error = __prepend_path(path->dentry, real_mount(path->mnt), root, &b);173 if (!(seq & 1))174 rcu_read_unlock();175 if (need_seqretry(&rename_lock, seq)) {176 seq = 1;177 goto restart;178 }179 done_seqretry(&rename_lock, seq);180 181 if (!(m_seq & 1))182 rcu_read_unlock();183 if (need_seqretry(&mount_lock, m_seq)) {184 m_seq = 1;185 goto restart_mnt;186 }187 done_seqretry(&mount_lock, m_seq);188 189 if (unlikely(error == 3))190 b = *p;191 192 if (b.len == p->len)193 prepend_char(&b, '/');194 195 *p = b;196 return error;197}198 199/**200 * __d_path - return the path of a dentry201 * @path: the dentry/vfsmount to report202 * @root: root vfsmnt/dentry203 * @buf: buffer to return value in204 * @buflen: buffer length205 *206 * Convert a dentry into an ASCII path name.207 *208 * Returns a pointer into the buffer or an error code if the209 * path was too long.210 *211 * "buflen" should be positive.212 *213 * If the path is not reachable from the supplied root, return %NULL.214 */215char *__d_path(const struct path *path,216 const struct path *root,217 char *buf, int buflen)218{219 DECLARE_BUFFER(b, buf, buflen);220 221 prepend_char(&b, 0);222 if (unlikely(prepend_path(path, root, &b) > 0))223 return NULL;224 return extract_string(&b);225}226 227char *d_absolute_path(const struct path *path,228 char *buf, int buflen)229{230 struct path root = {};231 DECLARE_BUFFER(b, buf, buflen);232 233 prepend_char(&b, 0);234 if (unlikely(prepend_path(path, &root, &b) > 1))235 return ERR_PTR(-EINVAL);236 return extract_string(&b);237}238 239static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)240{241 unsigned seq;242 243 do {244 seq = read_seqcount_begin(&fs->seq);245 *root = fs->root;246 } while (read_seqcount_retry(&fs->seq, seq));247}248 249/**250 * d_path - return the path of a dentry251 * @path: path to report252 * @buf: buffer to return value in253 * @buflen: buffer length254 *255 * Convert a dentry into an ASCII path name. If the entry has been deleted256 * the string " (deleted)" is appended. Note that this is ambiguous.257 *258 * Returns a pointer into the buffer or an error code if the path was259 * too long. Note: Callers should use the returned pointer, not the passed260 * in buffer, to use the name! The implementation often starts at an offset261 * into the buffer, and may leave 0 bytes at the start.262 *263 * "buflen" should be positive.264 */265char *d_path(const struct path *path, char *buf, int buflen)266{267 DECLARE_BUFFER(b, buf, buflen);268 struct path root;269 270 /*271 * We have various synthetic filesystems that never get mounted. On272 * these filesystems dentries are never used for lookup purposes, and273 * thus don't need to be hashed. They also don't need a name until a274 * user wants to identify the object in /proc/pid/fd/. The little hack275 * below allows us to generate a name for these objects on demand:276 *277 * Some pseudo inodes are mountable. When they are mounted278 * path->dentry == path->mnt->mnt_root. In that case don't call d_dname279 * and instead have d_path return the mounted path.280 */281 if (path->dentry->d_op && path->dentry->d_op->d_dname &&282 (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))283 return path->dentry->d_op->d_dname(path->dentry, buf, buflen);284 285 rcu_read_lock();286 get_fs_root_rcu(current->fs, &root);287 if (unlikely(d_unlinked(path->dentry)))288 prepend(&b, " (deleted)", 11);289 else290 prepend_char(&b, 0);291 prepend_path(path, &root, &b);292 rcu_read_unlock();293 294 return extract_string(&b);295}296EXPORT_SYMBOL(d_path);297 298/*299 * Helper function for dentry_operations.d_dname() members300 */301char *dynamic_dname(char *buffer, int buflen, const char *fmt, ...)302{303 va_list args;304 char temp[64];305 int sz;306 307 va_start(args, fmt);308 sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;309 va_end(args);310 311 if (sz > sizeof(temp) || sz > buflen)312 return ERR_PTR(-ENAMETOOLONG);313 314 buffer += buflen - sz;315 return memcpy(buffer, temp, sz);316}317 318char *simple_dname(struct dentry *dentry, char *buffer, int buflen)319{320 DECLARE_BUFFER(b, buffer, buflen);321 /* these dentries are never renamed, so d_lock is not needed */322 prepend(&b, " (deleted)", 11);323 prepend(&b, dentry->d_name.name, dentry->d_name.len);324 prepend_char(&b, '/');325 return extract_string(&b);326}327 328/*329 * Write full pathname from the root of the filesystem into the buffer.330 */331static char *__dentry_path(const struct dentry *d, struct prepend_buffer *p)332{333 const struct dentry *dentry;334 struct prepend_buffer b;335 int seq = 0;336 337 rcu_read_lock();338restart:339 dentry = d;340 b = *p;341 read_seqbegin_or_lock(&rename_lock, &seq);342 while (!IS_ROOT(dentry)) {343 const struct dentry *parent = dentry->d_parent;344 345 prefetch(parent);346 if (!prepend_name(&b, &dentry->d_name))347 break;348 dentry = parent;349 }350 if (!(seq & 1))351 rcu_read_unlock();352 if (need_seqretry(&rename_lock, seq)) {353 seq = 1;354 goto restart;355 }356 done_seqretry(&rename_lock, seq);357 if (b.len == p->len)358 prepend_char(&b, '/');359 return extract_string(&b);360}361 362char *dentry_path_raw(const struct dentry *dentry, char *buf, int buflen)363{364 DECLARE_BUFFER(b, buf, buflen);365 366 prepend_char(&b, 0);367 return __dentry_path(dentry, &b);368}369EXPORT_SYMBOL(dentry_path_raw);370 371char *dentry_path(const struct dentry *dentry, char *buf, int buflen)372{373 DECLARE_BUFFER(b, buf, buflen);374 375 if (unlikely(d_unlinked(dentry)))376 prepend(&b, "//deleted", 10);377 else378 prepend_char(&b, 0);379 return __dentry_path(dentry, &b);380}381 382static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,383 struct path *pwd)384{385 unsigned seq;386 387 do {388 seq = read_seqcount_begin(&fs->seq);389 *root = fs->root;390 *pwd = fs->pwd;391 } while (read_seqcount_retry(&fs->seq, seq));392}393 394/*395 * NOTE! The user-level library version returns a396 * character pointer. The kernel system call just397 * returns the length of the buffer filled (which398 * includes the ending '\0' character), or a negative399 * error value. So libc would do something like400 *401 * char *getcwd(char * buf, size_t size)402 * {403 * int retval;404 *405 * retval = sys_getcwd(buf, size);406 * if (retval >= 0)407 * return buf;408 * errno = -retval;409 * return NULL;410 * }411 */412SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)413{414 int error;415 struct path pwd, root;416 char *page = __getname();417 418 if (!page)419 return -ENOMEM;420 421 rcu_read_lock();422 get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);423 424 if (unlikely(d_unlinked(pwd.dentry))) {425 rcu_read_unlock();426 error = -ENOENT;427 } else {428 unsigned len;429 DECLARE_BUFFER(b, page, PATH_MAX);430 431 prepend_char(&b, 0);432 if (unlikely(prepend_path(&pwd, &root, &b) > 0))433 prepend(&b, "(unreachable)", 13);434 rcu_read_unlock();435 436 len = PATH_MAX - b.len;437 if (unlikely(len > PATH_MAX))438 error = -ENAMETOOLONG;439 else if (unlikely(len > size))440 error = -ERANGE;441 else if (copy_to_user(buf, b.buf, len))442 error = -EFAULT;443 else444 error = len;445 }446 __putname(page);447 return error;448}449