diff --git a/include/sway/config.h b/include/sway/config.h index 192e697c..2c6b83e7 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -202,6 +202,7 @@ enum secure_feature { FEATURE_FULLSCREEN = 16, FEATURE_KEYBOARD = 32, FEATURE_MOUSE = 64, + FEATURE_IPC = 128, }; struct feature_policy { diff --git a/sway/commands.c b/sway/commands.c index 47f7533c..3d8f8c5b 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -542,16 +542,15 @@ struct cmd_results *config_commands_command(char *exec) { { "criteria", CONTEXT_CRITERIA }, { "all", CONTEXT_ALL }, }; - size_t names_len = 5; for (int i = 1; i < argc; ++i) { size_t j; - for (j = 0; j < names_len; ++j) { + for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { if (strcmp(context_names[j].name, argv[i]) == 0) { break; } } - if (j == names_len) { + if (j == sizeof(context_names) / sizeof(context_names[0])) { results = cmd_results_new(CMD_INVALID, cmd, "Invalid command context %s", argv[i]); goto cleanup; diff --git a/sway/commands/permit.c b/sway/commands/permit.c index 258ea5b2..7a25e4ce 100644 --- a/sway/commands/permit.c +++ b/sway/commands/permit.c @@ -19,17 +19,17 @@ static enum secure_feature get_features(int argc, char **argv, { "fullscreen", FEATURE_FULLSCREEN }, { "keyboard", FEATURE_KEYBOARD }, { "mouse", FEATURE_MOUSE }, + { "ipc", FEATURE_IPC }, }; - size_t names_len = 7; for (int i = 1; i < argc; ++i) { size_t j; - for (j = 0; j < names_len; ++j) { + for (j = 0; j < sizeof(feature_names) / sizeof(feature_names[0]); ++j) { if (strcmp(feature_names[j].name, argv[i]) == 0) { break; } } - if (j == names_len) { + if (j == sizeof(feature_names) / sizeof(feature_names[0])) { *error = cmd_results_new(CMD_INVALID, "permit", "Invalid feature grant %s", argv[i]); return 0; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 15791c5e..c04c465a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -15,6 +15,7 @@ #include #include "sway/ipc-json.h" #include "sway/ipc-server.h" +#include "sway/security.h" #include "sway/config.h" #include "sway/commands.h" #include "sway/input.h" @@ -124,6 +125,17 @@ struct sockaddr_un *ipc_user_sockaddr(void) { return ipc_sockaddr; } +static pid_t get_client_pid(int client_fd) { + struct ucred ucred; + socklen_t len = sizeof(struct ucred); + + if (getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { + return -1; + } + + return ucred.pid; +} + int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; (void) data; sway_log(L_DEBUG, "Event on IPC listening socket"); @@ -142,6 +154,15 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { return 0; } + pid_t pid = get_client_pid(client_fd); + if (!(get_feature_policy(pid) & FEATURE_IPC)) { + sway_log(L_INFO, "Permission to connect to IPC socket denied to %d", pid); + const char *error = "{\"success\": false, \"message\": \"Permission denied\"}"; + write(client_fd, &error, sizeof(error)); + close(client_fd); + return 0; + } + struct ipc_client* client = malloc(sizeof(struct ipc_client)); client->payload_length = 0; client->fd = client_fd; diff --git a/sway/security.c b/sway/security.c index 2ccc30fd..0d510253 100644 --- a/sway/security.c +++ b/sway/security.c @@ -7,7 +7,7 @@ struct feature_policy *alloc_feature_policy(const char *program) { struct feature_policy *policy = malloc(sizeof(struct feature_policy)); policy->program = strdup(program); - policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE; + policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE | FEATURE_IPC; return policy; } diff --git a/sway/sway-security.7.txt b/sway/sway-security.7.txt index a4122c5c..53c7b876 100644 --- a/sway/sway-security.7.txt +++ b/sway/sway-security.7.txt @@ -81,6 +81,9 @@ policies. These features are: Permission to become fullscreen. Note that users can always make a window fullscreen themselves with the fullscreen command. +**ipc**:: + Permission to connect to sway's IPC socket. + **keyboard**:: Permission to receive keyboard events (only while they are focused). @@ -98,9 +101,9 @@ policies. These features are: **screenshot**:: Permission to take screenshots or record the screen. -By default, all programs are granted **fullscreen**, **keyboard**, and **mouse** -permissions. You can use the following config commands to control a program's -access: +By default, all programs are granted **fullscreen**, **keyboard**, **mouse**, and +**ipc** permissions. You can use the following config commands to control a +program's access: **permit** :: Permits to use (each feature seperated by a space).