mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 05:41:37 +00:00
[LibOS] Add readlinkat syscall implementation
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user