[LibOS] Add readlinkat syscall implementation

This commit is contained in:
borysp
2020-09-05 00:47:45 +02:00
committed by Michał Kowalczyk
parent dc094fcfaf
commit 9024e2cf50
4 changed files with 45 additions and 19 deletions
+3 -2
View File
@@ -410,7 +410,7 @@ int shim_do_mkdir(const char* pathname, int mode);
int shim_do_rmdir(const char* pathname);
int shim_do_creat(const char* path, mode_t mode);
int shim_do_unlink(const char* file);
int shim_do_readlink(const char* file, char* buf, size_t bufsize);
int shim_do_readlink(const char* file, char* buf, int bufsize);
int shim_do_chmod(const char* filename, mode_t mode);
int shim_do_fchmod(int fd, mode_t mode);
int shim_do_chown(const char* filename, uid_t user, gid_t group);
@@ -476,6 +476,7 @@ int shim_do_openat(int dfd, const char* filename, int flags, int mode);
int shim_do_mkdirat(int dfd, const char* pathname, int mode);
int shim_do_newfstatat(int dirfd, const char* pathname, struct stat* statbuf, int flags);
int shim_do_unlinkat(int dfd, const char* pathname, int flag);
int shim_do_readlinkat(int dirfd, const char* file, char* buf, int bufsize);
int shim_do_renameat(int olddfd, const char* pathname, int newdfd, const char* newname);
int shim_do_fchmodat(int dfd, const char* filename, mode_t mode);
int shim_do_fchownat(int dfd, const char* filename, uid_t user, gid_t group, int flags);
@@ -599,7 +600,7 @@ int shim_creat(const char* path, mode_t mode);
int shim_link(const char* oldname, const char* newname);
int shim_unlink(const char* file);
int shim_symlink(const char* old, const char* new);
int shim_readlink(const char* file, char* buf, size_t bufsize);
int shim_readlink(const char* file, char* buf, int bufsize);
int shim_chmod(const char* filename, mode_t mode);
int shim_fchmod(int fd, mode_t mode);
int shim_chown(const char* filename, uid_t user, gid_t group);
+3 -2
View File
@@ -392,7 +392,7 @@ DEFINE_SHIM_SYSCALL(unlink, 1, shim_do_unlink, int, const char*, file)
SHIM_SYSCALL_RETURN_ENOSYS(symlink, 2, int, const char*, old, const char*, new)
/* readlink: sys/shim_stat.c */
DEFINE_SHIM_SYSCALL(readlink, 3, shim_do_readlink, int, const char*, path, char*, buf, size_t,
DEFINE_SHIM_SYSCALL(readlink, 3, shim_do_readlink, int, const char*, path, char*, buf, int,
bufsize)
DEFINE_SHIM_SYSCALL(chmod, 2, shim_do_chmod, int, const char*, filename, mode_t, mode)
@@ -904,7 +904,8 @@ SHIM_SYSCALL_RETURN_ENOSYS(linkat, 5, int, int, olddfd, const char*, oldname, in
SHIM_SYSCALL_RETURN_ENOSYS(symlinkat, 3, int, const char*, oldname, int, newdfd, const char*,
newname)
SHIM_SYSCALL_RETURN_ENOSYS(readlinkat, 4, int, int, dfd, const char*, path, char*, buf, int, bufsiz)
DEFINE_SHIM_SYSCALL(readlinkat, 4, shim_do_readlinkat, int, int, dfd, const char*, path, char*, buf,
int, bufsiz)
/* fchmodat: sys/shim_fs.c */
DEFINE_SHIM_SYSCALL(fchmodat, 3, shim_do_fchmodat, int, int, dfd, const char*, filename, mode_t,
+26 -13
View File
@@ -92,22 +92,27 @@ out:
return ret;
}
int shim_do_readlink(const char* file, char* buf, size_t bufsize) {
int shim_do_readlinkat(int dirfd, const char* file, char* buf, int bufsize) {
if (!file || test_user_string(file))
return -EFAULT;
if (!buf || !bufsize || test_user_memory(buf, bufsize, true))
return -EFAULT;
if (bufsize <= 0)
return -EINVAL;
int ret;
if (test_user_memory(buf, bufsize, true))
return -EFAULT;
struct shim_dentry* dent = NULL;
struct shim_dentry* dir = NULL;
int ret = get_dirfd_dentry(dirfd, &dir);
if (ret < 0) {
goto out;
}
struct shim_qstr qstr = QSTR_INIT;
if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent, NULL)) < 0)
return ret;
if ((ret = path_lookupat(dir, file, LOOKUP_ACCESS, &dent, NULL)) < 0)
goto out;
ret = -EINVAL;
/* The correct behavior is to return -EINVAL if file is not a
@@ -122,17 +127,25 @@ int shim_do_readlink(const char* file, char* buf, size_t bufsize) {
if (ret < 0)
goto out;
ret = -ENAMETOOLONG;
if (qstr.len >= bufsize)
goto out;
ret = bufsize;
if (qstr.len < (size_t)bufsize)
ret = qstr.len;
memcpy(buf, qstrgetstr(&qstr), qstr.len);
ret = qstr.len;
memcpy(buf, qstrgetstr(&qstr), ret);
out:
put_dentry(dent);
if (dent) {
put_dentry(dent);
}
if (dir) {
put_dentry(dir);
}
return ret;
}
int shim_do_readlink(const char* file, char* buf, int bufsize) {
return shim_do_readlinkat(AT_FDCWD, file, buf, bufsize);
}
static int __do_statfs(struct shim_mount* fs, struct statfs* buf) {
__UNUSED(fs);
if (!buf || test_user_memory(buf, sizeof(*buf), true))
+13 -2
View File
@@ -1,4 +1,4 @@
#define _XOPEN_SOURCE 700
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -133,12 +133,23 @@ int main(int argc, char** argv) {
}
printf("===== Reading /proc/self/exe symlink\n");
ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
int proc_dirfd = open("/proc", O_DIRECTORY | O_PATH | O_RDONLY);
if (proc_dirfd < 0) {
perror("open /proc");
return 1;
}
ssize_t len = readlinkat(proc_dirfd, "self/exe", buf, sizeof(buf) - 1);
if (len < 0) {
perror("readlink /proc/self/exe");
return 1;
}
if (close(proc_dirfd) < 0) {
perror("close proc_dirfd");
return 1;
}
buf[len] = '\0';
printf("symlink /proc/self/exec resolves to %s\n", buf);