Hide semaphore info from user-space (WIP).
This commit is contained in:
+40
-41
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user