vfs: redo locking

This commit is contained in:
Matheus
2024-08-26 21:47:23 -03:00
parent da150523ba
commit 42bda0bf92
32 changed files with 271 additions and 169 deletions
+1 -1
View File
@@ -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);
+5 -3
View File
@@ -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();
+6
View File
@@ -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);
+2
View 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;
+7 -3
View File
@@ -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;
+1
View File
@@ -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:
+9 -2
View File
@@ -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);
+2
View File
@@ -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;
+2
View File
@@ -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);
+2
View 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;
+13 -7
View File
@@ -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);
+2
View File
@@ -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) {
+3
View File
@@ -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;
-4
View File
@@ -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));
+2
View File
@@ -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;
+6 -1
View File
@@ -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:
+2
View File
@@ -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;
+5
View File
@@ -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;
+2
View File
@@ -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;
+3 -2
View File
@@ -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:
+2
View File
@@ -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)
+8 -2
View File
@@ -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)
+3
View File
@@ -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;