diff options
author | Drew DeVault <sir@cmpwn.com> | 2016-12-02 18:08:15 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2016-12-02 18:09:19 -0500 |
commit | d353da248b4653d7bc027ff0dceca946cdd0b22f (patch) | |
tree | b76f5d9b8164a9eb102eee6b6cb13c5b9f6cbc75 | |
parent | Enforce IPC security policy (diff) | |
download | sway-d353da248b4653d7bc027ff0dceca946cdd0b22f.tar.gz sway-d353da248b4653d7bc027ff0dceca946cdd0b22f.tar.zst sway-d353da248b4653d7bc027ff0dceca946cdd0b22f.zip |
Add ipc connection feature policy controls
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | sway/commands.c | 5 | ||||
-rw-r--r-- | sway/commands/permit.c | 6 | ||||
-rw-r--r-- | sway/ipc-server.c | 21 | ||||
-rw-r--r-- | sway/security.c | 2 | ||||
-rw-r--r-- | sway/sway-security.7.txt | 9 |
6 files changed, 34 insertions, 10 deletions
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 { | |||
202 | FEATURE_FULLSCREEN = 16, | 202 | FEATURE_FULLSCREEN = 16, |
203 | FEATURE_KEYBOARD = 32, | 203 | FEATURE_KEYBOARD = 32, |
204 | FEATURE_MOUSE = 64, | 204 | FEATURE_MOUSE = 64, |
205 | FEATURE_IPC = 128, | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | struct feature_policy { | 208 | 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) { | |||
542 | { "criteria", CONTEXT_CRITERIA }, | 542 | { "criteria", CONTEXT_CRITERIA }, |
543 | { "all", CONTEXT_ALL }, | 543 | { "all", CONTEXT_ALL }, |
544 | }; | 544 | }; |
545 | size_t names_len = 5; | ||
546 | 545 | ||
547 | for (int i = 1; i < argc; ++i) { | 546 | for (int i = 1; i < argc; ++i) { |
548 | size_t j; | 547 | size_t j; |
549 | for (j = 0; j < names_len; ++j) { | 548 | for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { |
550 | if (strcmp(context_names[j].name, argv[i]) == 0) { | 549 | if (strcmp(context_names[j].name, argv[i]) == 0) { |
551 | break; | 550 | break; |
552 | } | 551 | } |
553 | } | 552 | } |
554 | if (j == names_len) { | 553 | if (j == sizeof(context_names) / sizeof(context_names[0])) { |
555 | results = cmd_results_new(CMD_INVALID, cmd, | 554 | results = cmd_results_new(CMD_INVALID, cmd, |
556 | "Invalid command context %s", argv[i]); | 555 | "Invalid command context %s", argv[i]); |
557 | goto cleanup; | 556 | 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, | |||
19 | { "fullscreen", FEATURE_FULLSCREEN }, | 19 | { "fullscreen", FEATURE_FULLSCREEN }, |
20 | { "keyboard", FEATURE_KEYBOARD }, | 20 | { "keyboard", FEATURE_KEYBOARD }, |
21 | { "mouse", FEATURE_MOUSE }, | 21 | { "mouse", FEATURE_MOUSE }, |
22 | { "ipc", FEATURE_IPC }, | ||
22 | }; | 23 | }; |
23 | size_t names_len = 7; | ||
24 | 24 | ||
25 | for (int i = 1; i < argc; ++i) { | 25 | for (int i = 1; i < argc; ++i) { |
26 | size_t j; | 26 | size_t j; |
27 | for (j = 0; j < names_len; ++j) { | 27 | for (j = 0; j < sizeof(feature_names) / sizeof(feature_names[0]); ++j) { |
28 | if (strcmp(feature_names[j].name, argv[i]) == 0) { | 28 | if (strcmp(feature_names[j].name, argv[i]) == 0) { |
29 | break; | 29 | break; |
30 | } | 30 | } |
31 | } | 31 | } |
32 | if (j == names_len) { | 32 | if (j == sizeof(feature_names) / sizeof(feature_names[0])) { |
33 | *error = cmd_results_new(CMD_INVALID, | 33 | *error = cmd_results_new(CMD_INVALID, |
34 | "permit", "Invalid feature grant %s", argv[i]); | 34 | "permit", "Invalid feature grant %s", argv[i]); |
35 | return 0; | 35 | 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 @@ | |||
15 | #include <libinput.h> | 15 | #include <libinput.h> |
16 | #include "sway/ipc-json.h" | 16 | #include "sway/ipc-json.h" |
17 | #include "sway/ipc-server.h" | 17 | #include "sway/ipc-server.h" |
18 | #include "sway/security.h" | ||
18 | #include "sway/config.h" | 19 | #include "sway/config.h" |
19 | #include "sway/commands.h" | 20 | #include "sway/commands.h" |
20 | #include "sway/input.h" | 21 | #include "sway/input.h" |
@@ -124,6 +125,17 @@ struct sockaddr_un *ipc_user_sockaddr(void) { | |||
124 | return ipc_sockaddr; | 125 | return ipc_sockaddr; |
125 | } | 126 | } |
126 | 127 | ||
128 | static pid_t get_client_pid(int client_fd) { | ||
129 | struct ucred ucred; | ||
130 | socklen_t len = sizeof(struct ucred); | ||
131 | |||
132 | if (getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { | ||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | return ucred.pid; | ||
137 | } | ||
138 | |||
127 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { | 139 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { |
128 | (void) fd; (void) data; | 140 | (void) fd; (void) data; |
129 | sway_log(L_DEBUG, "Event on IPC listening socket"); | 141 | sway_log(L_DEBUG, "Event on IPC listening socket"); |
@@ -142,6 +154,15 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
142 | return 0; | 154 | return 0; |
143 | } | 155 | } |
144 | 156 | ||
157 | pid_t pid = get_client_pid(client_fd); | ||
158 | if (!(get_feature_policy(pid) & FEATURE_IPC)) { | ||
159 | sway_log(L_INFO, "Permission to connect to IPC socket denied to %d", pid); | ||
160 | const char *error = "{\"success\": false, \"message\": \"Permission denied\"}"; | ||
161 | write(client_fd, &error, sizeof(error)); | ||
162 | close(client_fd); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
145 | struct ipc_client* client = malloc(sizeof(struct ipc_client)); | 166 | struct ipc_client* client = malloc(sizeof(struct ipc_client)); |
146 | client->payload_length = 0; | 167 | client->payload_length = 0; |
147 | client->fd = client_fd; | 168 | 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 @@ | |||
7 | struct feature_policy *alloc_feature_policy(const char *program) { | 7 | struct feature_policy *alloc_feature_policy(const char *program) { |
8 | struct feature_policy *policy = malloc(sizeof(struct feature_policy)); | 8 | struct feature_policy *policy = malloc(sizeof(struct feature_policy)); |
9 | policy->program = strdup(program); | 9 | policy->program = strdup(program); |
10 | policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE; | 10 | policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE | FEATURE_IPC; |
11 | return policy; | 11 | return policy; |
12 | } | 12 | } |
13 | 13 | ||
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: | |||
81 | Permission to become fullscreen. Note that users can always make a window | 81 | Permission to become fullscreen. Note that users can always make a window |
82 | fullscreen themselves with the fullscreen command. | 82 | fullscreen themselves with the fullscreen command. |
83 | 83 | ||
84 | **ipc**:: | ||
85 | Permission to connect to sway's IPC socket. | ||
86 | |||
84 | **keyboard**:: | 87 | **keyboard**:: |
85 | Permission to receive keyboard events (only while they are focused). | 88 | Permission to receive keyboard events (only while they are focused). |
86 | 89 | ||
@@ -98,9 +101,9 @@ policies. These features are: | |||
98 | **screenshot**:: | 101 | **screenshot**:: |
99 | Permission to take screenshots or record the screen. | 102 | Permission to take screenshots or record the screen. |
100 | 103 | ||
101 | By default, all programs are granted **fullscreen**, **keyboard**, and **mouse** | 104 | By default, all programs are granted **fullscreen**, **keyboard**, **mouse**, and |
102 | permissions. You can use the following config commands to control a program's | 105 | **ipc** permissions. You can use the following config commands to control a |
103 | access: | 106 | program's access: |
104 | 107 | ||
105 | **permit** <executable> <features...>:: | 108 | **permit** <executable> <features...>:: |
106 | Permits <executable> to use <features> (each feature seperated by a space). | 109 | Permits <executable> to use <features> (each feature seperated by a space). |