diff --git a/src/fuse_operations.c b/src/fuse_operations.c index 3f95315..a63837a 100644 --- a/src/fuse_operations.c +++ b/src/fuse_operations.c @@ -108,7 +108,29 @@ static int xmp_getattr(const char *path, struct stat *stbuf, static int xmp_access(const char *path, int mask) { int res; - res = access(path, mask); + // if mask is F_OK, then we don't need to check the permissions + // (is that possible?) + + if (mask != F_OK) { + struct process_info pi; + struct fuse_context *fc = fuse_get_context(); + + pi.PID = fc->pid; + pi.UID = fc->uid; + pi.name = get_process_name_by_pid(pi.PID); + + // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); + + if (!interactive_access(real_filename(path), pi)) { + free(pi.name); + return -EACCES; + } + + free(pi.name); + } + + res = source_access(path, mask); + if (res == -1) return -errno; @@ -304,6 +326,30 @@ static int xmp_rename(const char *from, const char *to, unsigned int flags) { if (flags) return -EINVAL; + struct process_info pi; + struct fuse_context *fc = fuse_get_context(); + + pi.PID = fc->pid; + pi.UID = fc->uid; + pi.name = get_process_name_by_pid(pi.PID); + + // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); + + if (!interactive_access(real_filename(from), pi)) { + free(pi.name); + return -EACCES; + } + + // the "to" file may exist and the process needs to get persmission to modify + // it + if (source_access(to, F_OK) == 0 && + !interactive_access(real_filename(to), pi)) { + free(pi.name); + return -EACCES; + } + + free(pi.name); + res = source_rename(from, to); if (res == -1) return -errno; @@ -313,6 +359,22 @@ static int xmp_rename(const char *from, const char *to, unsigned int flags) { static int xmp_link(const char *from, const char *to) { int res; + struct process_info pi; + struct fuse_context *fc = fuse_get_context(); + + pi.PID = fc->pid; + pi.UID = fc->uid; + pi.name = get_process_name_by_pid(pi.PID); + + // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); + if (!interactive_access(real_filename(from), pi)) { + free(pi.name); + return -EACCES; + } + + // no need to check the access to the "to" file, see link(2) + + free(pi.name); res = source_link(from, to); if (res == -1) @@ -323,6 +385,20 @@ static int xmp_link(const char *from, const char *to) { static int xmp_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) { int res; + struct process_info pi; + struct fuse_context *fc = fuse_get_context(); + + pi.PID = fc->pid; + pi.UID = fc->uid; + pi.name = get_process_name_by_pid(pi.PID); + + // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); + if (!interactive_access(real_filename(path), pi)) { + free(pi.name); + return -EACCES; + } + + free(pi.name); if (fi) res = fchmod(fi->fh, mode); @@ -334,9 +410,27 @@ static int xmp_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) { return 0; } +/** + * This filesystem is not designed for multiuser operation (e.g. with + * allow_other) so there is little point in having chown implemnted + */ static int xmp_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi) { int res; + struct process_info pi; + struct fuse_context *fc = fuse_get_context(); + + pi.PID = fc->pid; + pi.UID = fc->uid; + pi.name = get_process_name_by_pid(pi.PID); + + // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); + if (!interactive_access(real_filename(path), pi)) { + free(pi.name); + return -EACCES; + } + + free(pi.name); if (fi) res = fchown(fi->fh, uid, gid); @@ -660,7 +754,7 @@ static off_t xmp_lseek(const char *path, off_t off, int whence, static const struct fuse_operations xmp_oper = { .init = xmp_init, .getattr = xmp_getattr, - // .access = xmp_access, + .access = xmp_access, .readlink = xmp_readlink, .opendir = xmp_opendir, .readdir = xmp_readdir, @@ -676,7 +770,7 @@ static const struct fuse_operations xmp_oper = { .chown = xmp_chown, .truncate = xmp_truncate, #ifdef HAVE_UTIMENSAT -// .utimens = xmp_utimens, +// .utimens = xmp_utimens, #endif .create = xmp_create, .open = xmp_open, diff --git a/src/sourcefs.c b/src/sourcefs.c index 35dce28..78aea1d 100644 --- a/src/sourcefs.c +++ b/src/sourcefs.c @@ -66,6 +66,11 @@ int source_symlink(const char *target, const char *linkpath) { return symlinkat(target, handle.root_fd, relative_linkpath); } +int source_access(const char *filename, int mode) { + const char *relative_filename = source_filename_translate(filename); + return faccessat(handle.root_fd, relative_filename, mode, 0); +} + DIR *source_opendir(const char *filename) { const char *relative_filename = source_filename_translate(filename); int fd = openat(handle.root_fd, relative_filename, 0); diff --git a/src/sourcefs.h b/src/sourcefs.h index cd2dd4a..b712106 100644 --- a/src/sourcefs.h +++ b/src/sourcefs.h @@ -47,6 +47,8 @@ int source_chown(const char *filename, uid_t owner, gid_t group); int source_truncate(const char *filename, off_t length); +int source_access(const char *filename, int mode); + /* `open` and `create` are designed to correspond to fuse operations, not the * libc's `open(2)`. Both of them actually call `openat`. */