Hide semaphore info from user-space (WIP).

This commit is contained in:
Enrico Fraccaroli
2023-05-23 10:43:52 -04:00
parent a9d84f3a5d
commit e7c0334ac0
3 changed files with 84 additions and 73 deletions
+40 -41
View File
@@ -10,52 +10,51 @@
#include "assert.h"
#include "fcntl.h"
int ipc_valid_permissions(int flags, struct ipc_perm *perm)
int ipc_check_perm(
struct ipc_perm *perm,
int usr,
int grp,
int oth)
{
// Get the calling task.
task_struct *task = scheduler_get_current_process();
assert(task && "Failed to get the current running process.");
assert(perm && "Received a NULL ipc_perm.");
// Init process has unlimited power.
if (task->pid == 0)
return 1;
int check_parent = (perm->key < 0) && task->parent && (task->parent->pid != 0);
if ((perm->mode & usr)) {
if ((perm->uid == task->uid) || (perm->cuid == task->uid))
return 1;
if (check_parent && ((perm->uid == task->parent->uid) || (perm->cuid == task->parent->uid)))
return 1;
}
if ((perm->mode & grp)) {
if ((perm->gid == task->gid) || (perm->cgid == task->gid))
return 1;
if (check_parent && ((perm->gid == task->parent->gid) || (perm->cgid == task->parent->gid)))
return 1;
}
if ((perm->mode & oth)) {
if (check_parent && ((perm->uid == task->parent->uid) || (perm->cuid == task->parent->uid)))
return 1;
if (check_parent && ((perm->gid == task->parent->gid) || (perm->cgid == task->parent->gid)))
return 1;
}
return 0;
}
int ipc_valid_permissions(int flags, struct ipc_perm *perm)
{
// If the key is negative, it means it was a private key.
if (perm->key < 0) {
do {
if ((perm->uid == task->uid) || (perm->cuid == task->uid)) {
if (bitmask_check(flags, O_RDONLY) && bitmask_check(perm->mode, S_IRUSR))
return 1;
if (bitmask_check(flags, O_WRONLY) && bitmask_check(perm->mode, S_IWUSR))
return 1;
if (bitmask_check(flags, O_RDWR) && bitmask_check(perm->mode, S_IRUSR) && bitmask_check(perm->mode, S_IWUSR))
return 1;
}
task = task->parent;
} while (task && task->uid);
return 0;
}
// Check if the process itself has permissions.
if ((perm->uid == task->uid) || (perm->cuid == task->uid)) {
if (bitmask_check(flags, O_RDONLY) && !bitmask_check(perm->mode, S_IRUSR))
return 0;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(perm->mode, S_IWUSR))
return 0;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(perm->mode, S_IRUSR) || !bitmask_check(perm->mode, S_IWUSR)))
return 0;
}
if ((perm->gid == task->gid) || (perm->cgid == task->gid)) {
if (bitmask_check(flags, O_RDONLY) && !bitmask_check(perm->mode, S_IRGRP))
return 0;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(perm->mode, S_IWGRP))
return 0;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(perm->mode, S_IRGRP) || !bitmask_check(perm->mode, S_IWGRP)))
return 0;
}
if ((perm->uid != task->uid) && (perm->cuid != task->uid) && (perm->gid != task->gid) && (perm->cgid != task->gid)) {
if (bitmask_check(flags, O_RDONLY) && !bitmask_check(perm->mode, S_IROTH))
return 0;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(perm->mode, S_IWOTH))
return 0;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(perm->mode, S_IROTH) || !bitmask_check(perm->mode, S_IWOTH)))
return 0;
}
return 1;
if ((flags & O_RDONLY) && ipc_check_perm(perm, S_IRUSR, S_IRGRP, S_IROTH))
return 1;
if ((flags & O_WRONLY) && ipc_check_perm(perm, S_IWUSR, S_IWGRP, S_IWOTH))
return 1;
if ((flags & O_RDWR) && ipc_check_perm(perm, S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP, S_IROTH | S_IWOTH))
return 1;
return 0;
}
struct ipc_perm register_ipc(key_t key, mode_t mode)
+44 -28
View File
@@ -54,6 +54,15 @@
///@brief A value to compute the semid value.
int semid_assign = 0;
typedef struct {
/// @brief Semaphore ID associated to the semaphore set.
int id;
/// @brief The semaphore data strcutre.
struct semid_ds semid;
/// @brief List of all the semaphores.
struct sem *sems;
} sem_info_t;
/// @brief List of all current active semaphores.
list_t semaphores_list = {
.head = NULL,
@@ -61,6 +70,10 @@ list_t semaphores_list = {
.size = 0
};
// ============================================================================
// KEY GENERATION (Private)
// ============================================================================
/// Seed used to generate random numbers.
static int ipc_sem_rseed = 0;
/// The maximum value returned by the rand function.
@@ -76,6 +89,10 @@ static inline int ipc_sem_rand()
return ipc_sem_rseed = (ipc_sem_rseed * 1103515245U + 12345U) & IPC_SEM_RAND_MAX;
}
// ============================================================================
// MEMORY MANAGEMENT (Private)
// ============================================================================
/// @brief Allocates the memory for an array of semaphores.
/// @param nsems number of semaphores in the array.
/// @return a pointer to the allocated array of semaphores.
@@ -107,32 +124,28 @@ static inline void __sem_init(struct sem *ptr)
ptr->sem_zcnt = 0;
}
/// @brief Copies a semaphore from source to destination.
/// @param src source semaphore.
/// @param dst destination semaphore.
static inline void __sem_copy(struct sem *src, struct sem *dst)
{
assert(src && "Received a NULL source semaphore.");
assert(dst && "Received a NULL destination semaphore.");
memcpy(dst, src, sizeof(struct sem));
}
/// @brief Allocates the memory for a semid structure.
/// @return a pointer to the allocated semid structure.
static inline struct semid_ds *__semid_alloc()
static inline struct sem_info_t *__sem_info_alloc(int nsems)
{
// Allocate the memory.
struct semid_ds *ptr = (struct semid_ds *)kmalloc(sizeof(struct semid_ds));
sem_info_t *ptr = (sem_info_t *)kmalloc(sizeof(sem_info_t));
// Check the allocated memory.
assert(ptr && "Failed to allocate memory for a semid structure.");
// Clean the memory.
memset(ptr, 0, sizeof(struct semid_ds));
memset(ptr, 0, sizeof(sem_info_t));
// Allocate the memory for semaphores.
ptr->sems = (struct sem *)kmalloc(sizeof(struct sem) * nsems);
// Check the allocated memory.
assert(ptr && "Failed to allocate memory for a semid structure.");
// Clean the memory.
memset(ptr, 0, sizeof(sem_info_t));
return ptr;
}
/// @brief Frees the memory of a semid structure.
/// @param ptr pointer to the semid structure.
static inline void __semid_dealloc(struct semid_ds *ptr)
static inline void __sem_info_dealloc(struct semid_ds *ptr)
{
assert(ptr && "Received a NULL pointer.");
// Deallocate the array of semaphores.
@@ -146,7 +159,7 @@ static inline void __semid_dealloc(struct semid_ds *ptr)
/// @param key IPC_KEY associated with the set of semaphores
/// @param nsems number of semaphores to initialize
/// @todo The way we compute the semid is a temporary solution.
static inline void __semid_init(struct semid_ds *ptr, key_t key, int nsems, int semflg)
static inline void __sem_info_init(struct semid_ds *ptr, key_t key, int nsems, int semflg)
{
assert(ptr && "Received a NULL pointer.");
ptr->sem_perm = register_ipc(key, semflg & 0x1FF);
@@ -159,17 +172,9 @@ static inline void __semid_init(struct semid_ds *ptr, key_t key, int nsems, int
}
}
/// @brief Copies a semid from source to destination.
/// @param src source semid.
/// @param dst destination semid.
static inline void __semid_copy(struct semid_ds *src, struct semid_ds *dst)
{
assert(src && "Received a NULL source semid.");
assert(src->sems && "Received a source semid with NULL sems.");
assert(dst && "Received a NULL destination semid.");
assert(dst->sems && "Received a destination semid with NULL sems.");
memcpy(dst, src, sizeof(struct semid_ds));
}
// ============================================================================
// SEARCH FUNCTIONS (Private)
// ============================================================================
/// @brief Searches for the semaphore with the given id.
/// @param semid the id we are searching.
@@ -207,6 +212,10 @@ static inline struct semid_ds *__find_semaphore_by_key(key_t key)
return NULL;
}
// ============================================================================
// SYSTEM FUNCTIONS
// ============================================================================
long sys_semget(key_t key, int nsems, int semflg)
{
struct semid_ds *sem_set = NULL;
@@ -390,6 +399,11 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
pr_err("The array of semaphores inside the buffer is NULL.\n");
return -EINVAL;
}
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, sem_set->sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
// Copying all the data.
arg->buf->sem_perm = sem_set->sem_perm;
arg->buf->semid = sem_set->semid;
@@ -508,6 +522,10 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
return 0;
}
// ============================================================================
// PROCFS FUNCTIONS
// ============================================================================
ssize_t procipc_sem_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte)
{
if (!file) {
@@ -557,5 +575,3 @@ ssize_t procipc_sem_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte
}
return write_count;
}
///! @endcond