Skip to content
Merged
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
3 changes: 2 additions & 1 deletion cli/main.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "discovery.h"
#include "ratelimit.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -67,7 +68,7 @@ static pid_t parse_pid(const char *arg) {
char *endptr;
errno = 0;
long pid_long = strtol(arg, &endptr, 10);
if (errno != 0 || *endptr != '\0' || pid_long <= 0) {
if (errno != 0 || *endptr != '\0' || pid_long <= 0 || pid_long > INT_MAX) {
fprintf(stderr, "%s: invalid PID: %s\n", PROGRAM_NAME, arg);
exit(EXIT_FAILURE);
}
Expand Down
62 changes: 34 additions & 28 deletions gui/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <adwaita.h>
#include <errno.h>
#include <glib.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -42,17 +44,32 @@ static void handle_list_cmd(void) {
destroy_process_list(list);
}

static void handle_limit_cmd(pid_t pid, uint32_t upload, uint32_t download) {
static void handle_limit_cmd(const char *line) {
long pid, upload, download;
errno = 0;
if (sscanf(line, "%*ld %ld %ld %ld", &pid, &upload, &download) != 3 || errno != 0) {
printf("%d\n", BACKEND_RESPONSE_ERROR);
fflush(stdout);
return;
}
if (pid <= 0 || pid > INT_MAX || upload < 0 || upload > UINT32_MAX || download < 0 ||
download > UINT32_MAX) {
printf("%d\n", BACKEND_RESPONSE_ERROR);
fflush(stdout);
return;
}

ratelimit_code rc;
if (upload == RATELIMIT_UNLIMITED && download == RATELIMIT_UNLIMITED) {
// TODO: Check if it makes sense to clean using the monitor itself, instead of doing this.
rc = unregister_rate_limiter_by_pid(pid);
rc = unregister_rate_limiter_by_pid((pid_t)pid);
if (rc == RATELIMIT_CGROUP_NOT_FOUND) {
rc = RATELIMIT_OK;
}
} else {
rate_limit_config cfg = {.upload_kbps = upload, .download_kbps = download};
rc = limit_process_bandwidth(pid, cfg);
rate_limit_config cfg = {
.upload_kbps = (uint32_t)upload, .download_kbps = (uint32_t)download
};
rc = limit_process_bandwidth((pid_t)pid, cfg);
}

printf("%d\n", rc == RATELIMIT_OK ? BACKEND_RESPONSE_OK : BACKEND_RESPONSE_ERROR);
Expand All @@ -79,35 +96,24 @@ static int run_privileged(void) {

char line[64];
while (fgets(line, sizeof(line), stdin)) {
int cmd;
if (sscanf(line, "%d", &cmd) != 1) {
long cmd;
errno = 0;
if (sscanf(line, "%ld", &cmd) != 1 || errno != 0) {
continue;
}

if (cmd == BACKEND_CMD_LIST) {
switch (cmd) {
case BACKEND_CMD_LIST:
handle_list_cmd();
continue;
}

if (cmd == BACKEND_CMD_LIMIT) {
gint pid;
uint32_t upload, download;
if (sscanf(line, "%d %d %u %u", &cmd, &pid, &upload, &download) == 4) {
handle_limit_cmd(pid, upload, download);
} else {
printf("%d\n", BACKEND_RESPONSE_ERROR);
}
fflush(stdout);
continue;
}

if (cmd == BACKEND_CMD_CLEAN) {
break;
case BACKEND_CMD_LIMIT:
handle_limit_cmd(line);
break;
case BACKEND_CMD_CLEAN:
handle_clean_cmd();
continue;
}

if (cmd == BACKEND_CMD_QUIT) {
break;
case BACKEND_CMD_QUIT:
return EXIT_SUCCESS;
}
}

Expand Down
13 changes: 13 additions & 0 deletions lib/src/discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ static int add_process_list(process_list *list, pid_t pid, int is_tcp) {
if (len > 0 && proc->process_name[len - 1] == '\n') {
proc->process_name[len - 1] = '\0';
}
// The process itself controls its comm (prctl/argv[0]), so strip
// control characters to prevent terminal escape injection.
for (char *p = proc->process_name; *p; p++) {
if ((unsigned char)*p < 0x20 || (unsigned char)*p == 0x7f) {
*p = '?';
}
}
}
fclose(f);
}
Expand All @@ -101,6 +108,12 @@ static int add_process_list(process_list *list, pid_t pid, int is_tcp) {
ssize_t len = readlink(path, proc->exe_path, sizeof(proc->exe_path) - 1);
if (len != -1) {
proc->exe_path[len] = '\0';
// Same here
for (char *p = proc->exe_path; *p; p++) {
if ((unsigned char)*p < 0x20 || (unsigned char)*p == 0x7f) {
*p = '?';
}
}
}

list->count++;
Expand Down
10 changes: 8 additions & 2 deletions lib/src/monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,17 @@ static void monitor_run(void) {

struct sockaddr_un addr;
struct stat st;
if (stat(MONITOR_SOCKET_DIR, &st) < 0) {
if (mkdir(MONITOR_SOCKET_DIR, 0700) < 0 && errno != EEXIST) {
// The directory may already exist; only trust it if it is a real
// root-owned directory and not a symlink.
if (lstat(MONITOR_SOCKET_DIR, &st) < 0) {
if (errno != ENOENT || mkdir(MONITOR_SOCKET_DIR, 0700) < 0 ||
lstat(MONITOR_SOCKET_DIR, &st) < 0) {
exit(1);
}
}
if (!S_ISDIR(st.st_mode) || st.st_uid != 0) {
exit(1);
}
unlink(MONITOR_SOCKET_PATH);

monitor_socket = socket(AF_UNIX, SOCK_STREAM, 0);
Expand Down
5 changes: 3 additions & 2 deletions lib/src/ratelimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <errno.h>
#include <fcntl.h>
#include <libcgroup.h>
#include <limits.h>
#include <linux/limits.h>
#include <linux/magic.h>
#include <stdio.h>
Expand Down Expand Up @@ -153,7 +154,7 @@ static ratelimit_code attach_bpf_programs(rate_limiter *limiter, rate_limit_conf
}

static void build_cgroup_name(pid_t pid, char *buf, size_t size) {
snprintf(buf, size, "%s/%d", CGROUP_NAME, pid);
snprintf(buf, size, "%s/%ld", CGROUP_NAME, (long)pid);
}

ratelimit_code ratelimit_init(void) {
Expand Down Expand Up @@ -309,7 +310,7 @@ ratelimit_code ratelimit_cleanup_all(void) {
char *endptr;
errno = 0;
long pid_long = strtol(info.path, &endptr, 10);
if (errno != 0 || *endptr != '\0' || pid_long <= 0) {
if (errno != 0 || *endptr != '\0' || pid_long <= 0 || pid_long > INT_MAX) {
ret = cgroup_walk_tree_next(0, &handle, &info, base_level);
continue;
}
Expand Down
Loading