Added setXid/getXid, chdir
This commit is contained in:
@@ -5,6 +5,10 @@ void sys_exit(int status);
|
||||
int sys_kill(int pid, int signum);
|
||||
int sys_waitpid(int pid, int *status);
|
||||
int sys_getpid(void);
|
||||
int sys_setuid(uid_t uid);
|
||||
int sys_setgid(gid_t gid);
|
||||
uid_t sys_getuid(void);
|
||||
gid_t sys_getgid(void);
|
||||
|
||||
// Non-compliant with linux style, but fuck'em, it just works
|
||||
void sys_signal(uintptr_t entry);
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
int sys_nanosleep(const struct timespec *req, struct timespec *rem);
|
||||
int sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg);
|
||||
|
||||
int sys_mount(const char *dev_name, const char *dir_name, const char *type, unsigned long flags, void *data);
|
||||
|
||||
@@ -67,6 +67,7 @@ struct vnode {
|
||||
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
mode_t mode;
|
||||
|
||||
struct fs *fs;
|
||||
void *fs_data;
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
#define SYSCALL_NR_EXIT 60
|
||||
#define SYSCALL_NR_KILL 62
|
||||
#define SYSCALL_NR_GETTIMEOFDAY 96
|
||||
#define SYSCALL_NR_GETUID 102
|
||||
#define SYSCALL_NR_GETGID 104
|
||||
#define SYSCALL_NR_SETUID 105
|
||||
#define SYSCALL_NR_SETGID 106
|
||||
|
||||
#define SYSCALL_NR_MOUNT 165
|
||||
#define SYSCALL_NR_REBOOT 169
|
||||
|
||||
#define SYSCALL_NRX_OPENPTY 118
|
||||
|
||||
@@ -104,3 +104,39 @@ int sys_getpid(void) {
|
||||
_assert(thr);
|
||||
return thr->pid;
|
||||
}
|
||||
|
||||
int sys_setuid(uid_t uid) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
|
||||
if (thr->ioctx.uid != 0) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
thr->ioctx.uid = uid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sys_setgid(gid_t gid) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
|
||||
if (thr->ioctx.gid != 0) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
thr->ioctx.gid = gid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uid_t sys_getuid(void) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
return thr->ioctx.uid;
|
||||
}
|
||||
|
||||
gid_t sys_getgid(void) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
return thr->ioctx.gid;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,37 @@
|
||||
#include "sys/errno.h"
|
||||
#include "sys/sched.h"
|
||||
|
||||
int sys_mount(const char *dev_name, const char *dir_name, const char *type, unsigned long flags, void *data) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
struct vnode *dev_node;
|
||||
void *dev;
|
||||
int res;
|
||||
_assert(thr);
|
||||
_assert(dir_name);
|
||||
|
||||
if (thr->ioctx.uid != 0) {
|
||||
// Only root can do that
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (dev_name) {
|
||||
if ((res = vfs_find(&thr->ioctx, thr->ioctx.cwd_vnode, dev_name, &dev_node)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// Check that it's a block device:
|
||||
if (dev_node->type != VN_BLK) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = dev_node->dev;
|
||||
} else {
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
return vfs_mount(&thr->ioctx, dir_name, dev, type, NULL);
|
||||
}
|
||||
|
||||
int sys_nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
struct thread *cur_thread = get_cpu()->thread;
|
||||
_assert(cur_thread);
|
||||
|
||||
@@ -35,8 +35,13 @@ const void *amd64_syscall_jmp_table[256] = {
|
||||
[SYSCALL_NRX_SIGRET] = sys_sigret,
|
||||
[SYSCALL_NRX_SIGNAL] = sys_signal,
|
||||
[SYSCALL_NRX_WAITPID] = sys_waitpid,
|
||||
[SYSCALL_NR_SETUID] = sys_setuid,
|
||||
[SYSCALL_NR_SETGID] = sys_setgid,
|
||||
[SYSCALL_NR_GETUID] = sys_getuid,
|
||||
[SYSCALL_NR_GETGID] = sys_getgid,
|
||||
|
||||
// System
|
||||
[SYSCALL_NR_MOUNT] = sys_mount,
|
||||
[SYSCALL_NR_REBOOT] = sys_reboot,
|
||||
[SYSCALL_NR_NANOSLEEP] = sys_nanosleep,
|
||||
[SYSCALL_NR_GETTIMEOFDAY] = sys_gettimeofday,
|
||||
|
||||
@@ -46,6 +46,9 @@ static void devfs_ensure_root(void) {
|
||||
if (!devfs_root) {
|
||||
devfs_root = vnode_create(VN_DIR, NULL);
|
||||
devfs_root->flags |= VN_MEMORY;
|
||||
devfs_root->mode = 0555;
|
||||
devfs_root->uid = 0;
|
||||
devfs_root->gid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +71,10 @@ int dev_add_link(const char *name, struct vnode *to) {
|
||||
|
||||
devfs_ensure_root();
|
||||
|
||||
node->mode = 0777;
|
||||
node->uid = 0;
|
||||
node->gid = 0;
|
||||
|
||||
vnode_attach(devfs_root, node);
|
||||
|
||||
return 0;
|
||||
@@ -94,6 +101,11 @@ int dev_add(enum dev_class cls, int subcls, void *dev, const char *name) {
|
||||
|
||||
node->flags |= VN_MEMORY;
|
||||
|
||||
// Default permissions for devices
|
||||
node->mode = 0600;
|
||||
node->uid = 0;
|
||||
node->gid = 0;
|
||||
|
||||
devfs_ensure_root();
|
||||
|
||||
// TODO: some devices are located in subdirs
|
||||
|
||||
@@ -113,6 +113,10 @@ static struct vnode *ext2_fs_get_root(struct fs *fs) {
|
||||
res->op = &ext2_vnode_ops;
|
||||
res->type = ext2_inode_type(inode);
|
||||
|
||||
res->uid = inode->uid;
|
||||
res->gid = inode->gid;
|
||||
res->mode = inode->type_perm;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
+27
-27
@@ -29,7 +29,7 @@ static ssize_t ext2_vnode_write(struct ofile *fd, const void *buf, size_t count)
|
||||
static int ext2_vnode_truncate(struct vnode *vn, size_t length);
|
||||
static ssize_t ext2_vnode_readdir(struct ofile *fd, struct dirent *ent);
|
||||
//static void ext2_vnode_destroy(vnode_t *vn);
|
||||
//static int ext2_vnode_stat(vnode_t *vn, struct stat *st);
|
||||
static int ext2_vnode_stat(struct vnode *vn, struct stat *st);
|
||||
//static int ext2_vnode_chmod(vnode_t *vn, mode_t mode);
|
||||
//static int ext2_vnode_chown(vnode_t *vn, uid_t uid, gid_t gid);
|
||||
//static int ext2_vnode_unlink(vnode_t *at, vnode_t *vn, const char *name);
|
||||
@@ -48,7 +48,7 @@ struct vnode_operations ext2_vnode_ops = {
|
||||
//
|
||||
// .chmod = ext2_vnode_chmod,
|
||||
// .chown = ext2_vnode_chown,
|
||||
// .stat = ext2_vnode_stat,
|
||||
.stat = ext2_vnode_stat,
|
||||
// .unlink = ext2_vnode_unlink,
|
||||
// .access = ext2_vnode_access,
|
||||
//
|
||||
@@ -550,31 +550,31 @@ static ssize_t ext2_vnode_readdir(struct ofile *fd, struct dirent *vfsdir) {
|
||||
// // Release inode struct
|
||||
// kfree(vn->fs_data);
|
||||
//}
|
||||
//
|
||||
//static int ext2_vnode_stat(vnode_t *vn, struct stat *st) {
|
||||
// _assert(vn && vn->fs);
|
||||
// struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data;
|
||||
// _assert(inode);
|
||||
// struct ext2_extsb *sb = (struct ext2_extsb *) vn->fs->fs_private;
|
||||
// _assert(sb);
|
||||
//
|
||||
// st->st_atime = inode->atime;
|
||||
// st->st_ctime = inode->ctime;
|
||||
// st->st_mtime = inode->mtime;
|
||||
// st->st_dev = 0; // Not implemented
|
||||
// st->st_rdev = 0; // Not implemented
|
||||
// st->st_gid = inode->gid;
|
||||
// st->st_uid = inode->uid;
|
||||
// st->st_mode = inode->type_perm;
|
||||
// st->st_size = inode->size_lower;
|
||||
// st->st_blocks = (inode->size_lower + sb->block_size - 1) / sb->block_size;
|
||||
// st->st_blksize = sb->block_size;
|
||||
// st->st_nlink = 0;
|
||||
// st->st_ino = vn->fs_number;
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
|
||||
static int ext2_vnode_stat(struct vnode *vn, struct stat *st) {
|
||||
_assert(vn && vn->fs);
|
||||
struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data;
|
||||
_assert(inode);
|
||||
struct ext2_extsb *sb = (struct ext2_extsb *) vn->fs->fs_private;
|
||||
_assert(sb);
|
||||
|
||||
st->st_atime = inode->atime;
|
||||
st->st_ctime = inode->ctime;
|
||||
st->st_mtime = inode->mtime;
|
||||
st->st_dev = 0; // Not implemented
|
||||
st->st_rdev = 0; // Not implemented
|
||||
st->st_gid = inode->gid;
|
||||
st->st_uid = inode->uid;
|
||||
st->st_mode = inode->type_perm;
|
||||
st->st_size = inode->size_lower;
|
||||
st->st_blocks = (inode->size_lower + sb->block_size - 1) / sb->block_size;
|
||||
st->st_blksize = sb->block_size;
|
||||
st->st_nlink = 0;
|
||||
st->st_ino = vn->ino;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//static int ext2_vnode_chmod(vnode_t *vn, mode_t mode) {
|
||||
// _assert(vn && vn->fs && vn->fs_data);
|
||||
// struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data;
|
||||
|
||||
@@ -28,6 +28,10 @@ struct vnode *vnode_create(enum vnode_type t, const char *name) {
|
||||
node->op = NULL;
|
||||
node->dev = NULL;
|
||||
|
||||
node->uid = 0;
|
||||
node->gid = 0;
|
||||
node->mode = 0644;
|
||||
|
||||
if (name) {
|
||||
_assert(strlen(name) < NODE_MAXLEN);
|
||||
strcpy(node->name, name);
|
||||
|
||||
+7
-2
@@ -127,6 +127,10 @@ static int tar_init(struct fs *tar, const char *opt) {
|
||||
tar_root->fs = tar;
|
||||
tar_root->flags |= VN_MEMORY;
|
||||
|
||||
tar_root->uid = 0;
|
||||
tar_root->gid = 0;
|
||||
tar_root->mode = 0555;
|
||||
|
||||
struct vnode *node;
|
||||
|
||||
while (1) {
|
||||
@@ -160,8 +164,9 @@ static int tar_init(struct fs *tar, const char *opt) {
|
||||
_assert(node);
|
||||
|
||||
// Initialize the vnode
|
||||
node->uid = 0;
|
||||
node->gid = 0;
|
||||
node->uid = tarfs_octal(hdr->uid, 8);
|
||||
node->gid = tarfs_octal(hdr->gid, 8);
|
||||
node->mode = tarfs_octal(hdr->mode, 8);
|
||||
|
||||
struct tarfs_vnode_attr *attr = kmalloc(sizeof(struct tarfs_vnode_attr));
|
||||
_assert(attr);
|
||||
|
||||
+47
-31
@@ -2,6 +2,7 @@
|
||||
#include "sys/fs/fs.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/fcntl.h"
|
||||
#include "sys/panic.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/errno.h"
|
||||
@@ -15,9 +16,15 @@ struct vfs_ioctx *const kernel_ioctx = &_kernel_ioctx;
|
||||
|
||||
int vfs_setcwd(struct vfs_ioctx *ctx, const char *path) {
|
||||
struct vnode *node;
|
||||
struct vnode *dst;
|
||||
int res;
|
||||
|
||||
if (path[0] == '/') {
|
||||
if (path[1] == 0) {
|
||||
ctx->cwd_vnode = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vfs_root) {
|
||||
ctx->cwd_vnode = NULL;
|
||||
} else {
|
||||
@@ -25,8 +32,24 @@ int vfs_setcwd(struct vfs_ioctx *ctx, const char *path) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: access, check if directory
|
||||
ctx->cwd_vnode = node;
|
||||
// Resolve mounts and symlinks
|
||||
if ((res = vfs_link_resolve(ctx, node, &dst)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (dst->type == VN_MNT) {
|
||||
_assert(dst->target);
|
||||
dst = dst->target;
|
||||
}
|
||||
if (dst->type != VN_DIR) {
|
||||
return -ENOTDIR;
|
||||
}
|
||||
|
||||
if ((res = vfs_access_node(ctx, dst, X_OK)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ctx->cwd_vnode = dst;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
@@ -34,8 +57,23 @@ int vfs_setcwd(struct vfs_ioctx *ctx, const char *path) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: access, check if directory
|
||||
ctx->cwd_vnode = node;
|
||||
if ((res = vfs_link_resolve(ctx, node, &dst)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (dst->type == VN_MNT) {
|
||||
_assert(dst->target);
|
||||
dst = dst->target;
|
||||
}
|
||||
if (dst->type != VN_DIR) {
|
||||
return -ENOTDIR;
|
||||
}
|
||||
|
||||
if ((res = vfs_access_node(ctx, dst, X_OK)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ctx->cwd_vnode = dst;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -56,31 +94,8 @@ void vfs_vnode_path(char *path, struct vnode *node) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bstp = 10;
|
||||
while (node) {
|
||||
if (bstp == 0) {
|
||||
panic("Node stack overflow\n");
|
||||
}
|
||||
|
||||
backstack[--bstp] = node;
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
for (size_t i = bstp; i < 10; ++i) {
|
||||
size_t len;
|
||||
if (backstack[i]->parent) {
|
||||
// Non-root
|
||||
len = strlen(backstack[i]->name);
|
||||
strcpy(path + c, backstack[i]->name);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
c += len;
|
||||
if (i != 9) {
|
||||
path[c] = '/';
|
||||
}
|
||||
++c;
|
||||
}
|
||||
path[0] = '?';
|
||||
path[1] = 0;
|
||||
}
|
||||
|
||||
static const char *path_element(const char *path, char *element) {
|
||||
@@ -234,13 +249,14 @@ static int vfs_find_internal(struct vfs_ioctx *ctx, struct vnode *at, const char
|
||||
++path;
|
||||
}
|
||||
|
||||
child_path = path;
|
||||
while (1) {
|
||||
child_path = path_element(path, name);
|
||||
child_path = path_element(child_path, name);
|
||||
|
||||
if (!strcmp(name, ".")) {
|
||||
// Refers to this node
|
||||
kdebug(". hit %s\n", at->name);
|
||||
if (!child_path) {
|
||||
if (!child_path || !*child_path) {
|
||||
*child = at;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,11 +60,14 @@ int vfs_access_node(struct vfs_ioctx *ctx, struct vnode *vn, int mode) {
|
||||
_assert(vn);
|
||||
|
||||
if (!vn->op || !vn->op->access) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((res = vn->op->access(vn, &vn_uid, &vn_gid, &vn_mode)) != 0) {
|
||||
return res;
|
||||
vn_mode = vn->mode;
|
||||
vn_uid = vn->uid;
|
||||
vn_gid = vn->gid;
|
||||
} else {
|
||||
// Filesystem has non-trivial permission storage
|
||||
if ((res = vn->op->access(vn, &vn_uid, &vn_gid, &vn_mode)) != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return vfs_access_check(ctx, mode, vn_mode, vn_uid, vn_gid);
|
||||
|
||||
+5
-1
@@ -256,6 +256,11 @@ int vfs_creat(struct vfs_ioctx *ctx, const char *path, mode_t mode) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// Check permission for writing
|
||||
if ((res = vfs_access_node(ctx, at, W_OK)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: check if such file already exists
|
||||
if (!at->op || !at->op->creat) {
|
||||
// Assume it's a read-only filesystem
|
||||
@@ -338,7 +343,6 @@ int vfs_stat(struct vfs_ioctx *ctx, const char *path, struct stat *st) {
|
||||
}
|
||||
|
||||
if (!node->op || !node->op->stat) {
|
||||
kwarn("%s: filesystem has no stat()\n", path);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user