14 Commits

Author SHA1 Message Date
BritishTeapot
4ce97555e4 Fixed a testing bug
The script was correctly opening the `truth` file by piping `echo` to
it, but then it tried to deny another operation on it. But since pipes
are opened by the script process, the permission was given to the
script. And since the permissions are preserved for the entire runtime
of a process, and child processes inherit permissions of their parents,
any command executed later would also have the necessary permissions to
open `truth` (which was the case for the second operation). Now the
second operation is performed on a different file.
2025-03-24 17:17:33 +01:00
BritishTeapot
da37376fde Added permission checks for chmod, link, rename and chown
Those clearly need to ask for permissions.
2025-03-24 17:11:01 +01:00
BritishTeapot
6342de0dd3 Added tests to Makefile 2025-03-24 16:28:56 +01:00
BritishTeapot
2e21ae7b18 Deleted a useless file. 2025-03-18 16:50:53 +01:00
2d76dc6596 Merge pull request 'Temp_permission_table' (#5) from Temp_permission_table into main
Reviewed-on: #5
2025-03-18 15:47:08 +01:00
BritishTeapot
b705228685 Made temporary process table work!
Temprorary permissions table now works! It needs a better way for
cleaning though.
2025-03-18 15:45:32 +01:00
BritishTeapot
fe4b8801c0 Moved permission table logic to a separate file 2025-03-18 14:02:42 +01:00
BritishTeapot
e1846440bc Merge branch 'main' into Temp_permission_table 2025-03-18 14:00:57 +01:00
BritishTeapot
47a8845013 Wrote more tests 2025-03-18 13:58:02 +01:00
BritishTeapot
b6ce683364 WIP: Added the initial process table implementation.
Wrote a basic process table implementation with CC's vectors and hash
maps. So far, it looks like it does not really work.
2025-03-18 10:07:45 +01:00
BritishTeapot
70e81d64c1 Added the CC (Convenient Containers) library.
Added the CC library for vectors and hash maps.
2025-03-18 10:05:12 +01:00
BritishTeapot
67a148c7aa Fixed inverted access control permissions bug.
Fixed an (admitedly quite silly) bug that caused the access control
descisions to be inverted.
2025-03-18 10:03:32 +01:00
BritishTeapot
c59123330f Updated .gitignore 2025-03-18 09:55:20 +01:00
730d6bc27d Merge pull request 'Testing' (#4) from Testing into main
Reviewed-on: #4
2025-03-18 09:53:25 +01:00
13 changed files with 6910 additions and 68 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ build/*
.clang-tidy .clang-tidy
.cache .cache
test/protected/* test/protected/*
compile_commands.json

View File

@@ -43,7 +43,7 @@ endif
# set up targets # set up targets
TARGETS := icfs TARGETS := $(BUILD_DIR)/icfs
ifeq ($(TEST), 1) ifeq ($(TEST), 1)
TARGETS += icfs_test TARGETS += icfs_test
@@ -56,12 +56,11 @@ default: $(TARGETS)
.PHONY: clean .PHONY: clean
icfs: $(BUILD_DIR)/main.o $(BUILD_DIR)/fuse_operations.o $(BUILD_DIR)/sourcefs.o $(BUILD_DIR)/ui-socket.o $(BUILD_DIR)/icfs: $(BUILD_DIR)/main.o $(BUILD_DIR)/fuse_operations.o $(BUILD_DIR)/sourcefs.o $(BUILD_DIR)/ui-socket.o $(BUILD_DIR)/temp_permissions_table.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $(BUILD_DIR)/icfs $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $(BUILD_DIR)/icfs
icfs_test: $(BUILD_DIR)/main.o $(BUILD_DIR)/fuse_operations.o $(BUILD_DIR)/sourcefs.o $(BUILD_DIR)/ui-socket.o icfs_test: $(BUILD_DIR)/icfs
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $(BUILD_DIR)/icfs_test cd ./test && ./test.bash
# $(BUILD_DIR)/icfs_test # TODO: implement testing
$(BUILD_DIR)/test_access_control.o: $(TESTS_DIR)/test_access_control.c $(BUILD_DIR)/test_access_control.o: $(TESTS_DIR)/test_access_control.c
$(CC) $(CFLAGS) -c $< $(LDFLAGS) -o $@ $(CC) $(CFLAGS) -c $< $(LDFLAGS) -o $@
@@ -78,5 +77,8 @@ $(BUILD_DIR)/sourcefs.o: $(SOURCES_DIR)/sourcefs.c $(SOURCES_DIR)/sourcefs.h
$(BUILD_DIR)/ui-socket.o: $(SOURCES_DIR)/ui-socket.c $(SOURCES_DIR)/ui-socket.h $(BUILD_DIR)/ui-socket.o: $(SOURCES_DIR)/ui-socket.c $(SOURCES_DIR)/ui-socket.h
$(CC) $(CFLAGS) -c $< $(LDFLAGS) -o $@ $(CC) $(CFLAGS) -c $< $(LDFLAGS) -o $@
$(BUILD_DIR)/temp_permissions_table.o: $(SOURCES_DIR)/temp_permissions_table.c $(SOURCES_DIR)/temp_permissions_table.h
$(CC) $(CFLAGS) -c $< $(LDFLAGS) -o $@
clean: clean:
rm $(BUILD_DIR)/*.o $(BUILD_DIR)/icfs* rm $(BUILD_DIR)/*.o $(BUILD_DIR)/icfs*

6418
src/cc.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -108,7 +108,29 @@ static int xmp_getattr(const char *path, struct stat *stbuf,
static int xmp_access(const char *path, int mask) { static int xmp_access(const char *path, int mask) {
int res; 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) if (res == -1)
return -errno; return -errno;
@@ -264,7 +286,7 @@ static int xmp_unlink(const char *path) {
// fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi));
if (interactive_access(real_filename(path), pi)) { if (!interactive_access(real_filename(path), pi)) {
free(pi.name); free(pi.name);
return -EACCES; return -EACCES;
} }
@@ -304,6 +326,30 @@ static int xmp_rename(const char *from, const char *to, unsigned int flags) {
if (flags) if (flags)
return -EINVAL; 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); res = source_rename(from, to);
if (res == -1) if (res == -1)
return -errno; 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) { static int xmp_link(const char *from, const char *to) {
int res; 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); res = source_link(from, to);
if (res == -1) 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) { static int xmp_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
int res; 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) if (fi)
res = fchmod(fi->fh, mode); 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; 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, static int xmp_chown(const char *path, uid_t uid, gid_t gid,
struct fuse_file_info *fi) { struct fuse_file_info *fi) {
int res; 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) if (fi)
res = fchown(fi->fh, uid, gid); res = fchown(fi->fh, uid, gid);
@@ -392,7 +486,7 @@ static int xmp_create(const char *path, mode_t mode,
// fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi));
if (interactive_access(real_filename(path), pi)) { if (!interactive_access(real_filename(path), pi)) {
free(pi.name); free(pi.name);
return -EACCES; return -EACCES;
} }
@@ -417,7 +511,7 @@ static int xmp_open(const char *path, struct fuse_file_info *fi) {
pi.name = get_process_name_by_pid(pi.PID); pi.name = get_process_name_by_pid(pi.PID);
// fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi));
if (interactive_access(real_filename(path), pi)) { if (!interactive_access(real_filename(path), pi)) {
free(pi.name); free(pi.name);
return -EACCES; return -EACCES;
} }
@@ -660,7 +754,7 @@ static off_t xmp_lseek(const char *path, off_t off, int whence,
static const struct fuse_operations xmp_oper = { static const struct fuse_operations xmp_oper = {
.init = xmp_init, .init = xmp_init,
.getattr = xmp_getattr, .getattr = xmp_getattr,
// .access = xmp_access, .access = xmp_access,
.readlink = xmp_readlink, .readlink = xmp_readlink,
.opendir = xmp_opendir, .opendir = xmp_opendir,
.readdir = xmp_readdir, .readdir = xmp_readdir,
@@ -676,7 +770,7 @@ static const struct fuse_operations xmp_oper = {
.chown = xmp_chown, .chown = xmp_chown,
.truncate = xmp_truncate, .truncate = xmp_truncate,
#ifdef HAVE_UTIMENSAT #ifdef HAVE_UTIMENSAT
// .utimens = xmp_utimens, // .utimens = xmp_utimens,
#endif #endif
.create = xmp_create, .create = xmp_create,
.open = xmp_open, .open = xmp_open,

View File

@@ -36,7 +36,7 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ret = init_ui_socket("/home/fedir/.icfs-sock"); ret = init_ui_socket();
if (ret != 0) { if (ret != 0) {
perror("init_ui_socket"); perror("init_ui_socket");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -45,5 +45,6 @@ int main(int argc, char *argv[]) {
ret = fuse_main(argc, argv, get_fuse_operations(), NULL); ret = fuse_main(argc, argv, get_fuse_operations(), NULL);
free(mountpoint); free(mountpoint);
destroy_ui_socket();
return ret; return ret;
} }

12
src/process_info.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef PROCESS_INFO_H
#define PROCESS_INFO_H
#include <sys/types.h>
struct process_info {
pid_t PID;
const char *name;
uid_t UID;
};
#endif // PROCESS_INFO_H

View File

@@ -66,6 +66,11 @@ int source_symlink(const char *target, const char *linkpath) {
return symlinkat(target, handle.root_fd, relative_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) { DIR *source_opendir(const char *filename) {
const char *relative_filename = source_filename_translate(filename); const char *relative_filename = source_filename_translate(filename);
int fd = openat(handle.root_fd, relative_filename, 0); int fd = openat(handle.root_fd, relative_filename, 0);

View File

@@ -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_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 /* `open` and `create` are designed to correspond to fuse operations, not the
* libc's `open(2)`. Both of them actually call `openat`. */ * libc's `open(2)`. Both of them actually call `openat`. */

View File

@@ -0,0 +1,232 @@
/*
ICFS: Interactively Controlled File System
Copyright (C) 2024-2025 Fedir Kovalov
This program can be distributed under the terms of the GNU GPLv2.
See the file LICENSE.
*/
#include "temp_permissions_table.h"
#include "cc.h"
#include "process_info.h"
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
struct temp_process_permissions {
// yes, this is a correct type for start time in jiffies (see
// proc_pid_stat(5))
unsigned long long creation_time;
vec(char *) allowed_files;
};
map(pid_t, struct temp_process_permissions) temp_permissions_table;
pthread_mutex_t temp_permissions_table_lock;
/**
* Function to get the process creation time (in jiffies) from the proc
* filesystem
*
* @param pid: The process ID of the process to get the creation time of
* @return: The process creation time in jiffies, or 0 on error
* @note: although nothing in the documentation says that the creation time is
* never really equal to 0, it exceptionally unlikely.
*/
unsigned long long get_process_creation_time(pid_t pid) {
char path[32];
FILE *fp;
unsigned long long creation_time = 0;
// Construct the path to the process's status file
snprintf(path, sizeof(path), "/proc/%u/stat", pid);
// Open the status file
fp = fopen(path, "r");
if (fp == NULL) {
perror("fopen");
return 0;
}
// Read the creation time (the 22nd field in the stat file)
for (int i = 1; i < 22; i++) {
if (fscanf(fp, "%*s") == EOF) {
fprintf(stderr, "Error reading process stat file on the number %d\n", i);
fclose(fp);
return 0;
}
}
if (fscanf(fp, "%llu", &creation_time) != 1) {
fprintf(stderr, "Error reading creation time\n");
fclose(fp);
return 0;
}
// Close the file
fclose(fp);
return creation_time;
}
/**
* Initializes the temporary permissions table.
*
* @return: 0 on success, -1 on failure (e.g. ENOMEM)
*/
int init_temp_permissions_table() {
pthread_mutex_init(&temp_permissions_table_lock, PTHREAD_MUTEX_DEFAULT);
init(&temp_permissions_table);
}
/**
* Destroys the temporary permissions table.
*
* @note: the table is guranteed to be destroyed if it is already initialized
*/
void destroy_temp_permissions_table() {
// free the memory allocated for the table
for_each(&temp_permissions_table, entry) {
for_each(&entry->allowed_files, allowed_file) { free(*allowed_file); }
cleanup(&entry->allowed_files);
}
cleanup(&temp_permissions_table);
pthread_mutex_destroy(&temp_permissions_table_lock);
}
/**
* Checks if the process has a temporary access to the file.
*
* @param filename: The file that the process is trying to access
* @pram pid: PID of the process
* @return: 0 if access is denied, 1 if access is allowed
*/
int check_temp_access_noparent(const char *filename, pid_t pid) {
// TODO: more efficient locking
pthread_mutex_lock(&temp_permissions_table_lock);
struct temp_process_permissions *permission_entry =
get(&temp_permissions_table, pid);
if (permission_entry != NULL) {
unsigned long long process_creation_time = get_process_creation_time(pid);
if (process_creation_time == 0) {
perror("Could not retrieve process creation time");
pthread_mutex_unlock(&temp_permissions_table_lock);
return 0;
}
if (process_creation_time == permission_entry->creation_time) {
// the process is the same as the one that was granted temporary access
// to the file
for_each(&permission_entry->allowed_files, allowed_file) {
if (strncmp(*allowed_file, filename, strlen(filename)) == 0) {
pthread_mutex_unlock(&temp_permissions_table_lock);
return 1;
}
}
}
}
pthread_mutex_unlock(&temp_permissions_table_lock);
return 0;
}
/**
* Finds the parent process ID of a given process.
*
* @param pid: The process ID of the process to find the parent of
* @return: The parent process ID, or 0 if the parent process ID could not be
* found
*/
pid_t get_parent_pid(pid_t pid) {
pid_t ppid = 0;
char path[256];
snprintf(path, sizeof(path), "/proc/%u/status", pid);
FILE *file = fopen(path, "r");
if (file == NULL) {
perror("Failed to open /proc/<pid>/status");
return 0;
}
char line[256];
while (fgets(line, sizeof(line), file)) {
if (sscanf(line, "PPid:\t%d", &ppid) == 1) {
fclose(file);
return ppid;
}
}
fclose(file);
return 0; // Parent PID not found
}
/**
* Checks if the process or any of it's parents have temporary access to the
* file.
*
* @param filename: The file that the process is trying to access
* @pram pi: The process information
* @return: 0 if access is denied, 1 if access is allowed
* @note: In case one of the parent processes is killed while this function
* execution the result is not guranteed to be correct. It should only lead to
* false negatives, though.
*/
int check_temp_access(const char *filename, struct process_info pi) {
pid_t current_pid = pi.PID;
while (current_pid != 0) {
if (check_temp_access_noparent(filename, current_pid)) {
return 1;
}
current_pid = get_parent_pid(current_pid);
}
return 0;
}
/**
* Gives temporary access to the process to the file.
*
* @param filename: The file that the process is trying to access
* @param pi: The process information
* @return: 0 on success, -1 on failure (e.g. ENOMEM)
*/
int give_temp_access(const char *filename, struct process_info pi) {
pthread_mutex_lock(&temp_permissions_table_lock);
struct temp_process_permissions *permission_entry =
get(&temp_permissions_table, pi.PID);
if (permission_entry != NULL) {
unsigned long long process_creation_time =
get_process_creation_time(pi.PID);
if (process_creation_time == 0) {
perror("Could not retrieve process creation time");
pthread_mutex_unlock(&temp_permissions_table_lock);
return -1;
}
if (process_creation_time == permission_entry->creation_time) {
// the process is the same as the one that was granted temporary access
// to the file
push(&permission_entry->allowed_files, strdup(filename));
pthread_mutex_unlock(&temp_permissions_table_lock);
return 0;
}
// we have an entry for the process, but the process is different
// delete the entry and create a new one
erase(&temp_permissions_table, pi.PID);
permission_entry = NULL;
}
// no entry is present
// construct the entry
struct temp_process_permissions new_permission_entry;
new_permission_entry.creation_time = get_process_creation_time(pi.PID);
init(&new_permission_entry.allowed_files);
push(&new_permission_entry.allowed_files, strdup(filename));
insert(&temp_permissions_table, pi.PID, new_permission_entry);
printf("temp_permissions_table size: %ld\n", size(&temp_permissions_table));
pthread_mutex_unlock(&temp_permissions_table_lock);
return 0;
}

View File

@@ -0,0 +1,39 @@
#ifndef TEMP_PERMISSIONS_TABLE_H
#define TEMP_PERMISSIONS_TABLE_H
#include "process_info.h"
/**
* Initializes the temporary permissions table.
*
* @return: 0 on success, -1 on failure (e.g. ENOMEM)
*/
int init_temp_permissions_table();
/**
* Destroys the temporary permissions table.
*
* @note: the table is guranteed to be destroyed if it is already initialized
*/
void destroy_temp_permissions_table();
/**
* Checks if the process has a temporary access to the file.
*
* @param filename: The file that the process is trying to access
* @param pi: The process information
* @return: 0 if access is denied, 1 if access is allowed
*/
int check_temp_access(const char *filename, struct process_info pi);
/**
* Gives temporary access to the process to the file.
*
* @param filename: The file that the process is trying to access
* @param pi: The process information
* @return: 0 on success, -1 on failure (e.g. ENOMEM)
*/
int give_temp_access(const char *filename, struct process_info pi);
#endif // !TEMP_PERMISSIONS_TABLE_H

View File

@@ -8,7 +8,10 @@
#include <stddef.h> #include <stddef.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h>
#define _GNU_SOURCE #define _GNU_SOURCE
#include "cc.h"
#include "temp_permissions_table.h"
#include "ui-socket.h" #include "ui-socket.h"
#include <errno.h> #include <errno.h>
#include <pthread.h> #include <pthread.h>
@@ -19,23 +22,27 @@
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
int init_ui_socket(const char *filename) { int init_ui_socket() {
char line[256]; char line[256];
FILE *fp; FILE *fp;
init_temp_permissions_table();
// Test if Zenity is installed (get version) // Test if Zenity is installed (get version)
fp = popen("zenity --version", "r"); fp = popen("zenity --version", "r");
if (fp == NULL) { if (fp == NULL) {
perror("Pipe returned a error"); perror("Pipe returned an error");
return 1; return 1;
} else {
while (fgets(line, sizeof(line), fp))
printf("%s", line);
pclose(fp);
return 0;
} }
while (fgets(line, sizeof(line), fp))
printf("%s", line);
pclose(fp);
return 0;
} }
void destroy_ui_socket() { destroy_temp_permissions_table(); }
/** /**
* Asks the user if the process should be allowed to access the file using the * Asks the user if the process should be allowed to access the file using the
* GUI * GUI
@@ -71,25 +78,19 @@ int ask_access(const char *filename, struct process_info pi) {
// to manually check the output. // to manually check the output.
char buffer[1024]; char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
if (strcmp(buffer, "Allow this time.\n") == 0) { printf("%s", buffer);
if (strcmp(buffer, "Allow this time\n") == 0) {
pclose(fp); pclose(fp);
return 2; return 2;
} }
} }
int zenity_exit_code = WEXITSTATUS(pclose(fp)); int zenity_exit_code = WEXITSTATUS(pclose(fp));
return zenity_exit_code; // zenity returns 1 on "No" >:(
} if (zenity_exit_code == 0) {
return 1;
}
/**
* Checks if the process has a temporary access to the file.
*
* @param filename: The file that the process is trying to access
* @pram pi: The process information
* @return: 0 if access is denied, 1 if access is allowed
*/
int check_temp_access(const char *filename, struct process_info pi) {
perror("Not implemented");
return 0; return 0;
} }
@@ -104,12 +105,9 @@ int check_perm_access(const char *filename, struct process_info pi) {
perror("Not implemented"); perror("Not implemented");
return 0; return 0;
} }
int give_perm_access(const char *filename, struct process_info pi) {
void give_temp_access(const char *filename, struct process_info pi) {
perror("Not implemented");
}
void give_perm_access(const char *filename, struct process_info pi) {
perror("Not implemented"); perror("Not implemented");
return -1;
} }
/** /**

View File

@@ -13,17 +13,31 @@
#ifndef UI_SOCKET_H #ifndef UI_SOCKET_H
#define UI_SOCKET_H #define UI_SOCKET_H
#include "process_info.h"
#include <sys/types.h> #include <sys/types.h>
struct process_info { /**
pid_t PID; * Initialize the GUI communication.
const char *name; *
uid_t UID; * @return: 0 on success, -1 on faliure.
}; */
int init_ui_socket(void);
// For default socket location, set socket_path = NULL. /**
int init_ui_socket(const char *socket_path); * Close the GUI communication.
*/
void destroy_ui_socket(void);
/**
* Check access according to:
* 1. temporary permission table
* 2. permanent permission table
* 3. user descision
*
* @param filename: The file that the process is trying to access
* @pram pi: The process information
* @return: 0 if access is denied, 1 if access is allowed
*/
int interactive_access(const char *filename, struct process_info pi); int interactive_access(const char *filename, struct process_info pi);
#endif // !UI_SOCKET_H #endif // !UI_SOCKET_H

View File

@@ -4,8 +4,9 @@
rm -rf ./protected rm -rf ./protected
mkdir protected mkdir protected
touch ./protected/do-not-remove ./protected/should-be-removed touch ./protected/do-not-remove ./protected/should-be-removed ./protected/truth ./protected/perm000 ./protected/perm777 ./protected/should-be-renamed ./protected/do-not-rename
echo "Free code, free world." >./protected/this-only chmod 777 ./protected/perm777 ./protected/perm000
echo "Free code, free world." >./protected/motto
# set up the fake-zenity # set up the fake-zenity
@@ -18,42 +19,43 @@ valgrind -s ../build/icfs -o default_permissions ./protected &
sleep 1 sleep 1
# Try to touch files in the directory # create files
#echo \"manual\" >./protected/manual
zenity --set-fake-response no zenity --set-fake-response no
echo "first" >./protected/first 2>/dev/null && touch ./protected/should-not-exist 2>/dev/null &&
echo "[ICFS-TEST]: echo can create protected/first despite access being denied!" || echo "[ICFS-TEST]: touch can create protected/should-not-exist despite access being denied!" ||
echo "[ICFS-TEST]: OK" # EACCESS echo "[ICFS-TEST]: OK" # EACCESS
zenity --set-fake-response yes_tmp zenity --set-fake-response yes_tmp
echo "second" >./protected/second 2>/dev/null && touch ./protected/should-exist 2>/dev/null &&
echo "[ICFS-TEST]: OK" || echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: echo cannot create protected/second despite access being permitted!" # OK echo "[ICFS-TEST]: touch cannot create protected/should-exist despite access being permitted!" # OK
# Test whether permissons work # write to files
zenity --set-fake-response no
echo "Linux is a cancer that attaches itself in an intellectual property sense to everything it touches." >./protected/truth 2>/dev/null &&
echo "[ICFS-TEST]: echo can write to protected/lie despite access being denied!" ||
echo "[ICFS-TEST]: OK" # EACCESS
zenity --set-fake-response yes_tmp zenity --set-fake-response yes_tmp
cat ./protected/first >/dev/null 2>/dev/null && echo "Sharing knowledge is the most fundamental act of friendship. Because it is a way you can give something without loosing something." >./protected/truth 2>/dev/null &&
echo "[ICFS-TEST]: cat can read a non-existant file ./protected/first!" || echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: OK" # ENOENT echo "[ICFS-TEST]: echo cannot write to protected/truth despite access being permitted!" # OK
# Read files
zenity --set-fake-response no
cat ./protected/motto >/dev/null 2>/dev/null &&
echo "[ICFS-TEST]: cat can read protected/this-only despite access being denied!" ||
echo "[ICFS-TEST]: OK" # EACCESS
zenity --set-fake-response yes_tmp zenity --set-fake-response yes_tmp
cat ./protected/second >/dev/null 2>/dev/null && cat ./protected/motto >/dev/null 2>/dev/null &&
echo "[ICFS-TEST]: OK" || echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: cat cannot open protected/second despite access being permitted!" # "second" echo "[ICFS-TEST]: echo cannot create protected/this-only despite access being permitted!" # "Free code, free world."
zenity --set-fake-response yes_tmp # remove files
cat ./protected/this-only >/dev/null 2>/dev/null &&
echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: echo cannot create protected/second despite access being permitted!" # "Free code, free world."
#parallel ::: "cat ./protected/sudo-only > /dev/null 2> /dev/null \
# && echo \"[ICFS-TEST]: cat can access files owned by root!\" \
# || echo \"[ICFS-TEST]: OK\"" # EACCESS
# test the removal
zenity --set-fake-response no zenity --set-fake-response no
rm ./protected/do-not-remove >/dev/null 2>/dev/null && rm ./protected/do-not-remove >/dev/null 2>/dev/null &&
@@ -65,6 +67,28 @@ rm ./protected/should-be-removed >/dev/null 2>/dev/null &&
echo "[ICFS-TEST]: OK" || echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: rm cannot unlink protected/should-be-removed despite access being permitted!" # OK echo "[ICFS-TEST]: rm cannot unlink protected/should-be-removed despite access being permitted!" # OK
# rename files
zenity --set-fake-response no
mv ./protected/do-not-rename ./protected/terrible-name 2>/dev/null &&
echo "[ICFS-TEST]: mv can rename protected/truth despite access being denied!" ||
echo "[ICFS-TEST]: OK" # EACCESS
zenity --set-fake-response yes_tmp
mv ./protected/should-be-renamed ./protected/great-name 2>/dev/null &&
echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: mv cannot rename should-be-removed to renamed-file despite access being permitted!" # OK
# change permissions
zenity --set-fake-response no
chmod 000 ./protected/perm777 2>/dev/null &&
echo "[ICFS-TEST]: chmod can change permissions of protected/perm777 despite access being denied!" ||
echo "[ICFS-TEST]: OK" # EACCESS
zenity --set-fake-response yes_tmp
chmod 000 ./protected/perm000 2>/dev/null &&
echo "[ICFS-TEST]: OK" ||
echo "[ICFS-TEST]: chmod cannot change permissions of protected/perm000 despite access being permitted!" # OK
# unmount # unmount
sleep 0.5 sleep 0.5