diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 37459366f5..6b12d929fe 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -612,7 +612,7 @@ int sys_fstat(int file, struct stat *buf) { #ifdef ARCH_MM_MMU int ret = -1; - struct stat statbuff; + struct stat statbuff = {0}; if (!lwp_user_accessable((void *)buf, sizeof(struct stat))) { @@ -2575,7 +2575,45 @@ int sys_log(const char* log, int size) int sys_stat(const char *file, struct stat *buf) { int ret = 0; - ret = stat(file, buf); + int err; + size_t len; + size_t copy_len; + char *copy_path; + struct stat statbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct stat))) + { + return -EFAULT; + } + + len = lwp_user_strlen(file, &err); + if (err) + { + return -EFAULT; + } + + copy_path = (char*)rt_malloc(len + 1); + if (!copy_path) + { + return -ENOMEM; + } + + copy_len = lwp_get_from_user(copy_path, (void*)file, len); + if (copy_len == 0) + { + rt_free(copy_path); + return -EFAULT; + } + copy_path[copy_len] = '\0'; + + ret = stat(copy_path, &statbuff); + rt_free(copy_path); + + if (ret == 0) + { + lwp_put_to_user(buf, &statbuff, sizeof statbuff); + } + return (ret < 0 ? GET_ERRNO() : ret); } @@ -4157,6 +4195,67 @@ int sys_getrandom(void *buf, size_t buflen, unsigned int flags) #endif return ret; } + +ssize_t sys_readlink(char* path, char *buf, size_t bufsz) +{ + size_t len, copy_len; + int err; + int fd = -1; + struct dfs_fd *d; + char *copy_path; + + len = lwp_user_strlen(path, &err); + if (err) + { + return -EFAULT; + } + + if (!lwp_user_accessable(buf, bufsz)) + { + return -EINVAL; + } + + copy_path = (char*)rt_malloc(len + 1); + if (!copy_path) + { + return -ENOMEM; + } + + copy_len = lwp_get_from_user(copy_path, path, len); + copy_path[copy_len] = '\0'; + + /* musl __procfdname */ + err = sscanf(copy_path, "/proc/self/fd/%d", &fd); + rt_free(copy_path); + + if (err != 1) + { + LOG_E("readlink: path not is /proc/self/fd/* , call by musl __procfdname()?"); + return -EINVAL; + } + + d = fd_get(fd); + if (!d) + { + return -EBADF; + } + + if (!d->vnode) + { + return -EBADF; + } + + copy_len = strlen(d->vnode->fullpath); + if (copy_len > bufsz) + { + copy_len = bufsz; + } + + bufsz = lwp_put_to_user(buf, d->vnode->fullpath, copy_len); + + return bufsz; +} + int sys_setaffinity(pid_t pid, size_t size, void *set) { if (!lwp_user_accessable(set, sizeof(cpu_set_t))) @@ -4672,7 +4771,7 @@ const static void* func_table[] = SYSCALL_SIGN(sys_setrlimit), SYSCALL_SIGN(sys_setsid), SYSCALL_SIGN(sys_getrandom), - SYSCALL_SIGN(sys_notimpl), // SYSCALL_SIGN(sys_readlink) /* 145 */ + SYSCALL_SIGN(sys_readlink), // SYSCALL_SIGN(sys_readlink) /* 145 */ SYSCALL_USPACE(SYSCALL_SIGN(sys_mremap)), SYSCALL_USPACE(SYSCALL_SIGN(sys_madvise)), SYSCALL_SIGN(sys_sched_setparam),