mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
vfs: redo locking
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
static int filesystem(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2) {
|
||||
vnode_t *vnode = arg0;
|
||||
vnode_t *vnode = arg0; // expected locked
|
||||
|
||||
vattr_t attr;
|
||||
VOP_GETATTR(vnode, &attr, NULL);
|
||||
|
||||
@@ -760,11 +760,13 @@ void sched_runinit() {
|
||||
|
||||
vnode_t *consolenode;
|
||||
__assert(devfs_getbyname("console", &consolenode) == 0);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_READ | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||
VOP_LOCK(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_READ | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_HOLD(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_HOLD(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0)
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_UNLOCK(consolenode);
|
||||
|
||||
file_t *stdin = fd_allocate();
|
||||
file_t *stdout = fd_allocate();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel/auth.h>
|
||||
|
||||
// node expected to be locked
|
||||
static int dochmod(vnode_t *node, mode_t mode) {
|
||||
vattr_t attr;
|
||||
cred_t *cred = &_cpu()->thread->proc->cred;
|
||||
@@ -58,6 +59,9 @@ syscallret_t syscall_fchmodat(context_t *, int dirfd, char *upath, mode_t mode,
|
||||
ret.errno = dochmod(node, mode);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
|
||||
// locked by vfs_lookup
|
||||
VOP_UNLOCK(node);
|
||||
|
||||
cleanup:
|
||||
|
||||
if (node)
|
||||
@@ -82,8 +86,10 @@ syscallret_t syscall_fchmod(context_t *, int fd, mode_t mode) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = dochmod(file->vnode, mode);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
VOP_UNLOCK(file->vnode);
|
||||
|
||||
fd_release(file);
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ syscallret_t syscall_chroot(context_t *, char *upath) {
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
VOP_UNLOCK(new);
|
||||
|
||||
if (new->type != V_TYPE_DIR) {
|
||||
ret.errno = ENOTDIR;
|
||||
goto cleanup;
|
||||
|
||||
@@ -178,8 +178,10 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
|
||||
goto error;
|
||||
|
||||
ret.errno = VOP_ACCESS(node, V_ACCESS_EXECUTE, &_cpu()->thread->proc->cred);
|
||||
if (ret.errno)
|
||||
VOP_UNLOCK(node);
|
||||
if (ret.errno) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
size_t readcount;
|
||||
ret.errno = vfs_read(node, shebang, SHEBANG_SIZE - 1, 0, &readcount, 0);
|
||||
@@ -229,8 +231,6 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
|
||||
goto error;
|
||||
}
|
||||
|
||||
// TODO permission and type checks and all
|
||||
|
||||
vmm_switchcontext(vmmctx);
|
||||
|
||||
auxv64list_t auxv64;
|
||||
@@ -246,6 +246,8 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
|
||||
if (ret.errno)
|
||||
goto error;
|
||||
|
||||
VOP_UNLOCK(interpnode);
|
||||
|
||||
auxv64list_t interpauxv;
|
||||
char *interpinterp = NULL;
|
||||
ret.errno = elf_load(interpnode, INTERP_BASE, &entry, &interpinterp, &interpauxv);
|
||||
@@ -263,7 +265,9 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
|
||||
}
|
||||
|
||||
vattr_t vattr;
|
||||
VOP_LOCK(node);
|
||||
ret.errno = VOP_GETATTR(node, &vattr, NULL);
|
||||
VOP_UNLOCK(node);
|
||||
if (ret.errno)
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ syscallret_t syscall_faccessat(context_t *, int dirfd, char *upath, int mode, in
|
||||
goto cleanup;
|
||||
|
||||
ret.errno = VOP_ACCESS(node, mode, &_cpu()->thread->proc->cred);
|
||||
VOP_UNLOCK(node);
|
||||
ret.ret = 0;
|
||||
|
||||
cleanup:
|
||||
|
||||
@@ -27,6 +27,7 @@ syscallret_t syscall_fchownat(context_t *, int fd, char *upath, uid_t owner, gid
|
||||
|
||||
node = file->vnode;
|
||||
VOP_HOLD(node);
|
||||
VOP_LOCK(node);
|
||||
fd_release(file);
|
||||
} else {
|
||||
// chown is done on the file pointed to by the path relative to fd
|
||||
@@ -50,13 +51,17 @@ syscallret_t syscall_fchownat(context_t *, int fd, char *upath, uid_t owner, gid
|
||||
}
|
||||
|
||||
ret.errno = auth_filesystem_check(&_cpu()->thread->proc->cred, AUTH_ACTIONS_FILESYSTEM_SETATTR, node);
|
||||
if (ret.errno)
|
||||
if (ret.errno) {
|
||||
VOP_UNLOCK(node);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vattr_t attr;
|
||||
ret.errno = VOP_GETATTR(node, &attr, &_cpu()->thread->proc->cred);
|
||||
if (ret.errno)
|
||||
if (ret.errno) {
|
||||
VOP_UNLOCK(node);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// TODO retain set uid and set gid bits if an auth access was ok
|
||||
attr.uid = owner;
|
||||
@@ -66,6 +71,8 @@ syscallret_t syscall_fchownat(context_t *, int fd, char *upath, uid_t owner, gid
|
||||
ret.errno = VOP_SETATTR(node, &attr, ((owner == -1) ? 0 : V_ATTR_UID) | ((group == -1) ? 0 : V_ATTR_GID), &_cpu()->thread->proc->cred);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
|
||||
VOP_UNLOCK(node);
|
||||
|
||||
cleanup:
|
||||
if (node)
|
||||
VOP_RELEASE(node);
|
||||
|
||||
@@ -35,7 +35,9 @@ syscallret_t syscall_getdents(context_t *, int dirfd, void *ubuffer, size_t read
|
||||
}
|
||||
|
||||
size_t offset = fd->offset;
|
||||
VOP_LOCK(fd->vnode);
|
||||
ret.errno = VOP_GETDENTS(fd->vnode, buffer, count, offset, &ret.ret);
|
||||
VOP_UNLOCK(fd->vnode);
|
||||
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
@@ -19,7 +19,9 @@ syscallret_t syscall_ioctl(context_t *, int fd, unsigned long request, void *arg
|
||||
}
|
||||
|
||||
int r = 0;
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = VOP_IOCTL(file->vnode, request, arg, &r);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
ret.ret = ret.errno ? -1 : r;
|
||||
|
||||
fd_release(file);
|
||||
|
||||
@@ -14,7 +14,9 @@ syscallret_t syscall_isatty(context_t *context, int fd) {
|
||||
}
|
||||
|
||||
// mlibc expects isatty to return 1 if a terminal and 0 if not.
|
||||
VOP_LOCK(file->vnode);
|
||||
int e = VOP_ISATTY(file->vnode);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
|
||||
ret.errno = e;
|
||||
ret.ret = e ? 0 : 1;
|
||||
|
||||
@@ -43,16 +43,16 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
|
||||
int newfd;
|
||||
ret.errno = fd_new(flags & O_CLOEXEC, &newfile, &newfd);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
goto cleanup_nounlock;
|
||||
|
||||
vnode_t *vnode = NULL;
|
||||
ret.errno = vfs_open(dirnode, pathbuf, fileflagstovnodeflags(flags), &vnode);
|
||||
if (ret.errno == 0 && (flags & O_CREAT) && (flags & O_EXCL)) {
|
||||
// exclusive and file already exists
|
||||
ret.errno = EEXIST;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret.errno == ENOENT && (flags & O_CREAT)) {
|
||||
goto cleanup_nounlock;
|
||||
} else if (ret.errno == ENOENT && (flags & O_CREAT)) {
|
||||
// create file
|
||||
vattr_t attr = {
|
||||
.mode = UMASK(mode),
|
||||
.gid = _cpu()->thread->proc->cred.egid,
|
||||
@@ -62,6 +62,12 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
|
||||
ret.errno = vfs_create(dirnode, pathbuf, &attr, V_TYPE_REGULAR, &vnode);
|
||||
if (ret.errno == EEXIST && (flags & O_EXCL) == 0)
|
||||
goto retry_open;
|
||||
} else if (ret.errno) {
|
||||
// any other error
|
||||
goto cleanup_nounlock;
|
||||
} else {
|
||||
// success, lock file
|
||||
VOP_LOCK(vnode);
|
||||
}
|
||||
|
||||
if (ret.errno)
|
||||
@@ -78,9 +84,7 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
|
||||
goto cleanup;
|
||||
|
||||
if (vnode->type == V_TYPE_REGULAR && (flags & O_TRUNC) && (flags & FILE_WRITE)) {
|
||||
MUTEX_ACQUIRE(&vnode->sizelock, false);
|
||||
ret.errno = VOP_RESIZE(vnode, 0, &_cpu()->thread->proc->cred);
|
||||
MUTEX_RELEASE(&vnode->sizelock);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -95,6 +99,8 @@ syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags
|
||||
ret.ret = newfd;
|
||||
|
||||
cleanup:
|
||||
VOP_UNLOCK(vnode);
|
||||
cleanup_nounlock:
|
||||
if (vnode && ret.errno) {
|
||||
vfs_close(vnode, fileflagstovnodeflags(flags));
|
||||
VOP_RELEASE(vnode);
|
||||
|
||||
@@ -11,7 +11,9 @@ static void open(file_t *file, vnode_t *node, int flags) {
|
||||
file->flags = flags;
|
||||
file->offset = 0;
|
||||
file->mode = 0777;
|
||||
VOP_LOCK(node);
|
||||
VOP_OPEN(&node, fileflagstovnodeflags(flags) | V_FFLAGS_NONBLOCKING, &_cpu()->thread->proc->cred);
|
||||
VOP_UNLOCK(node);
|
||||
}
|
||||
|
||||
syscallret_t syscall_pipe2(context_t *, int flags) {
|
||||
|
||||
@@ -62,7 +62,10 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms
|
||||
|
||||
filebuff[i] = file;
|
||||
|
||||
VOP_LOCK(file->vnode);
|
||||
int revents = VOP_POLL(file->vnode, timeoutms == 0 ? NULL : &desc.data[i], fdsbuff[i].events);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
|
||||
if (revents) {
|
||||
fdsbuff[i].revents = revents;
|
||||
++eventcount;
|
||||
|
||||
@@ -35,10 +35,6 @@ syscallret_t syscall_pread(context_t *context, int fd, void *buffer, size_t size
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
vattr_t attr;
|
||||
VOP_GETATTR(file->vnode, &attr, NULL);
|
||||
|
||||
size_t bytesread;
|
||||
ret.errno = vfs_read(file->vnode, kernelbuff, size, offset, &bytesread, fileflagstovnodeflags(file->flags));
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ syscallret_t syscall_readlinkat(context_t *, int dirfd, char *upath, char *ubuff
|
||||
goto cleanup;
|
||||
|
||||
ret.errno = VOP_READLINK(node, &buffer, &_cpu()->thread->proc->cred);
|
||||
// locked by vfs_lookup
|
||||
VOP_UNLOCK(node);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
@@ -60,16 +60,21 @@ syscallret_t syscall_renameat(context_t *context, int olddirfd, char *uoldpath,
|
||||
if (oldcomponent == NULL && newcomponent == NULL)
|
||||
goto cleanup;
|
||||
|
||||
// TODO possibly deadlocks
|
||||
ret.errno = vfs_lookup(&sourcedirnode, olddirnode, oldpath, oldcomponent, VFS_LOOKUP_NOLINK | VFS_LOOKUP_PARENT);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
ret.errno = vfs_lookup(&targetdirnode, newdirnode, newpath, newcomponent, VFS_LOOKUP_NOLINK | VFS_LOOKUP_PARENT);
|
||||
if (ret.errno)
|
||||
if (ret.errno) {
|
||||
VOP_UNLOCK(sourcedirnode);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret.errno = VOP_RENAME(sourcedirnode, oldcomponent, targetdirnode, newcomponent, flags);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
VOP_UNLOCK(targetdirnode);
|
||||
VOP_UNLOCK(sourcedirnode);
|
||||
|
||||
cleanup:
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ syscallret_t syscall_seek(context_t *context, int fd, off_t offset, int whence)
|
||||
}
|
||||
} else {
|
||||
vattr_t attr;
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = VOP_GETATTR(file->vnode, &attr, &_cpu()->thread->proc->cred);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
size = attr.size;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <kernel/file.h>
|
||||
#include <kernel/alloc.h>
|
||||
|
||||
// vnode should be locked
|
||||
static int dostat(vnode_t *vnode, stat_t *stat) {
|
||||
vattr_t attr;
|
||||
int e = VOP_GETATTR(vnode, &attr, &_cpu()->thread->proc->cred);
|
||||
@@ -40,7 +41,9 @@ syscallret_t syscall_fstat(context_t *ctx, int fd, stat_t *ustat) {
|
||||
}
|
||||
|
||||
stat_t buf;
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = dostat(file->vnode, &buf);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
@@ -87,6 +90,8 @@ syscallret_t syscall_fstatat(context_t *ctx, int dirfd, char *upath, stat_t *ust
|
||||
|
||||
stat_t buf;
|
||||
ret.errno = dostat(node, &buf);
|
||||
// locked by vfs_lookup
|
||||
VOP_UNLOCK(node);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ syscallret_t syscall_fsync(context_t *context, int fd) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = VOP_SYNC(file->vnode);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
|
||||
fd_release(file);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
|
||||
@@ -17,9 +17,10 @@ syscallret_t syscall_ftruncate(int fd, size_t size) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
MUTEX_ACQUIRE(&file->vnode->sizelock, false);
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = VOP_RESIZE(file->vnode, size, &_cpu()->thread->proc->cred);
|
||||
MUTEX_RELEASE(&file->vnode->sizelock);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
|
||||
cleanup:
|
||||
|
||||
@@ -49,6 +49,8 @@ syscallret_t syscall_unlinkat(context_t *, int dirfd, char *upath, int flags) {
|
||||
|
||||
ret.errno = VOP_UNLINK(node, component, &_cpu()->thread->proc->cred);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
// locked by vfs_lookup
|
||||
VOP_UNLOCK(node);
|
||||
|
||||
cleanup:
|
||||
if (component)
|
||||
|
||||
@@ -32,6 +32,7 @@ syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[
|
||||
}
|
||||
|
||||
node = file->vnode;
|
||||
VOP_LOCK(node);
|
||||
VOP_HOLD(node);
|
||||
fd_release(file);
|
||||
} else {
|
||||
@@ -62,8 +63,10 @@ syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[
|
||||
|
||||
vattr_t attr;
|
||||
ret.errno = VOP_GETATTR(node, &attr, &_cpu()->thread->proc->cred);
|
||||
if (ret.errno)
|
||||
if (ret.errno) {
|
||||
VOP_UNLOCK(node);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
attr.atime = ts[0];
|
||||
attr.mtime = ts[1];
|
||||
@@ -73,12 +76,15 @@ syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[
|
||||
if (uts == NULL)
|
||||
ret.errno = VOP_ACCESS(node, V_ACCESS_WRITE, &_cpu()->thread->proc->cred);
|
||||
|
||||
if (ret.errno)
|
||||
if (ret.errno) {
|
||||
VOP_UNLOCK(node);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret.errno = VOP_SETATTR(node, &attr, V_ATTR_ATIME | V_ATTR_MTIME, &_cpu()->thread->proc->cred);
|
||||
ret.ret = ret.errno ? -1 : 0;
|
||||
VOP_UNLOCK(node);
|
||||
|
||||
cleanup:
|
||||
if (node)
|
||||
|
||||
@@ -36,7 +36,10 @@ syscallret_t syscall_write(context_t *context, int fd, void *buffer, size_t size
|
||||
|
||||
if (file->flags & O_APPEND) {
|
||||
vattr_t attr;
|
||||
// TODO racey
|
||||
VOP_LOCK(file->vnode);
|
||||
ret.errno = VOP_GETATTR(file->vnode, &attr, &_cpu()->thread->proc->cred);
|
||||
VOP_UNLOCK(file->vnode);
|
||||
if (ret.errno)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user