Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ OBJDUMP ?= $(CROSS_COMPILE)objdump

CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -I. -I$(VPATH)
CFLAGS += -Wall -Wextra -O2
LDFLAGS += -ltalloc -Wl,-z,noexecstack
LDFLAGS += -ltalloc -lpthread -Wl,-z,noexecstack

OBJECTS += \
cli/cli.o \
Expand Down
22 changes: 22 additions & 0 deletions src/extension/sysvipc/sysvipc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct SysVIpcSemaphore {
bool valid;
uint16_t *sems;
int nsems;
struct SysVIpcSemidDs stats;
};

/*****************
Expand Down Expand Up @@ -91,6 +92,7 @@ struct SysVIpcSharedMem {
bool valid;
bool rmid_pending;
int fd;
int x11_shmid; /* Termux:X11-compatible shmid for MIT-SHM */
struct SysVIpcShmidDs stats;

/**
Expand Down Expand Up @@ -223,6 +225,26 @@ struct SysVIpcConfig {
#define IPC_OBJECT_ID(index, object) \
((index + 1) | (object->generation << 12))

/**
* Find SHM object by x11_shmid (Termux:X11-compatible shmid).
*/
#define LOOKUP_SHM_OBJECT(out_index, out_object, objects_array) \
{ \
int object_id = peek_reg(tracee, CURRENT, SYSARG_1); \
int num_objects = (int)talloc_array_length(objects_array); \
out_index = (size_t)-1; \
for (int _i = 0; _i < num_objects; _i++) { \
if ((objects_array)[_i].valid && (objects_array)[_i].x11_shmid == object_id) { \
out_index = _i; \
break; \
} \
} \
if (out_index == (size_t)-1) { \
return -EINVAL; \
} \
out_object = &(objects_array)[out_index]; \
}

/**
* Iterate over all Tracees in given SysVIpc namespace
*
Expand Down
67 changes: 64 additions & 3 deletions src/extension/sysvipc/sysvipc_sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <sys/errno.h> /* E* */
#include <string.h> /* memset */
#include <assert.h> /* assert */
#include <time.h> /* time */

#define SYSVIPC_MAX_SEMS 512
#define SYSVIPC_MAX_NSEMS 512
Expand Down Expand Up @@ -59,6 +60,10 @@ int sysvipc_semget(Tracee *tracee, struct SysVIpcConfig *config) {
semaphore->sems = talloc_array(config->ipc_namespace, uint16_t, nsems);
memset(semaphore->sems, 0, nsems * sizeof(uint16_t));
semaphore->nsems = nsems;
memset(&semaphore->stats, 0, sizeof(semaphore->stats));
semaphore->stats.sem_ctime = time(NULL);
semaphore->stats.sem_nsems = nsems;
semaphore->stats.sem_perm.mode = semflg & 0777;
} else {
if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
return -EEXIST;
Expand Down Expand Up @@ -115,6 +120,7 @@ static int sysvipc_sem_check(struct SysVIpcConfig *config, struct SysVIpcSemapho
}
}
memcpy(semaphore->sems, new_sems, semaphore->nsems * sizeof(uint16_t));
semaphore->stats.sem_otime = time(NULL);

return 0;
}
Expand Down Expand Up @@ -211,6 +217,7 @@ int sysvipc_semctl(Tracee *tracee, struct SysVIpcConfig *config) {
if (cmdarg > SYSVIPC_MAX_SEMVAL) return -ERANGE;
if (semnum < 0 || semnum >= semaphore->nsems) return -EINVAL;
semaphore->sems[semnum] = cmdarg;
semaphore->stats.sem_ctime = time(NULL);
return 0;
}
case SYSVIPC_GETALL:
Expand All @@ -237,14 +244,68 @@ int sysvipc_semctl(Tracee *tracee, struct SysVIpcConfig *config) {
TALLOC_FREE(semaphore->sems);
return 0;
}
#if 0
case IPC_STAT:
case SYSVIPC_SEM_STAT:
case SYSVIPC_SEM_STAT_ANY:
{
int status = write_data(tracee, buf, &queue->stats, sizeof(struct msqid_ds));
semaphore->stats.sem_nsems = semaphore->nsems;
int status = write_data(tracee, cmdarg, &semaphore->stats, sizeof(struct SysVIpcSemidDs));
if (status < 0) return status;
if ((cmd & ~SYSVIPC_IPC_64) == SYSVIPC_SEM_STAT || (cmd & ~SYSVIPC_IPC_64) == SYSVIPC_SEM_STAT_ANY) {
return IPC_OBJECT_ID(semaphore_index, semaphore);
}
return 0;
}
#endif
case IPC_SET:
{
struct SysVIpcSemidDs buf;
int status = read_data(tracee, &buf, cmdarg, sizeof(struct SysVIpcSemidDs));
if (status < 0) return status;
semaphore->stats.sem_perm.uid = buf.sem_perm.uid;
semaphore->stats.sem_perm.gid = buf.sem_perm.gid;
semaphore->stats.sem_perm.mode = buf.sem_perm.mode & 0777;
semaphore->stats.sem_ctime = time(NULL);
return 0;
}
case SYSVIPC_GETPID:
{
if (semnum < 0 || semnum >= semaphore->nsems) return -EINVAL;
return 0; /* sempid not tracked, return 0 */
}
case SYSVIPC_GETNCNT:
{
if (semnum < 0 || semnum >= semaphore->nsems) return -EINVAL;
int count = 0;
Tracee *waiting_tracee;
struct SysVIpcConfig *waiting_config;
SYSVIPC_FOREACH_TRACEE(waiting_tracee, waiting_config, config->ipc_namespace) {
if (
waiting_config->wait_reason == WR_WAIT_SEMOP &&
waiting_config->waiting_object_index == semaphore_index) {
char wait_type = 0;
sysvipc_sem_check(waiting_config, semaphore, &wait_type);
if (wait_type == 'n') count++;
}
}
return count;
}
case SYSVIPC_GETZCNT:
{
if (semnum < 0 || semnum >= semaphore->nsems) return -EINVAL;
int count = 0;
Tracee *waiting_tracee;
struct SysVIpcConfig *waiting_config;
SYSVIPC_FOREACH_TRACEE(waiting_tracee, waiting_config, config->ipc_namespace) {
if (
waiting_config->wait_reason == WR_WAIT_SEMOP &&
waiting_config->waiting_object_index == semaphore_index) {
char wait_type = 0;
sysvipc_sem_check(waiting_config, semaphore, &wait_type);
if (wait_type == 'z') count++;
}
}
return count;
}
case SYSVIPC_IPC_INFO:
case SYSVIPC_SEM_INFO:
{
Expand Down
Loading