commit 1172566d4e298aa6c3555a0d606af4ff31d0db48
parent 14d9200e4e51c7c4597df65cbf0fb5347ef80caa
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 17 Dec 2016 15:19:50 -0500
Change how security config is loaded
Diffstat:
10 files changed, 80 insertions(+), 100 deletions(-)
diff --git a/config.d/security.in b/config.d/security.in
@@ -1,50 +0,0 @@
-# sway security rules
-#
-# Read sway-security(7) for details on how to secure your sway install.
-#
-# You MUST read this man page if you intend to attempt to secure your sway
-# installation.
-
-# Configures which programs are allowed to use which sway features
-permit * fullscreen keyboard mouse ipc
-permit __PREFIX__/bin/swaylock lock
-permit __PREFIX__/bin/swaybar panel
-permit __PREFIX__/bin/swaybg background
-permit __PREFIX__/bin/swaygrab screenshot
-
-# Configures which IPC features are enabled
-ipc {
- command enabled
- outputs enabled
- workspaces enabled
- tree enabled
- marks enabled
- bar-config enabled
- inputs enabled
-
- events {
- workspace enabled
- output enabled
- mode enabled
- window enabled
- input enabled
- binding disabled
- }
-}
-
-# Limits the contexts from which certain commands are permitted
-commands {
- * all
-
- fullscreen binding criteria
- bindsym config
- exit binding
- kill binding
-
- # You should not change these unless you know what you're doing - it could
- # cripple your security
- reload binding
- permit config
- reject config
- ipc config
-}
diff --git a/include/sway/config.h b/include/sway/config.h
@@ -373,4 +373,9 @@ struct bar_config *default_bar_config(void);
*/
extern struct sway_config *config;
+/**
+ * Config file currently being read.
+ */
+extern const char *current_config_path;
+
#endif
diff --git a/security.in b/security.in
@@ -0,0 +1,46 @@
+# sway security rules
+#
+# Read sway-security(7) for details on how to secure your sway install.
+#
+# You MUST read this man page if you intend to attempt to secure your sway
+# installation.
+#
+# This file should live at __SYSCONFDIR__/sway/security and will be
+# automatically read by sway.
+
+# Configures which programs are allowed to use which sway features
+permit * fullscreen keyboard mouse ipc
+permit __PREFIX__/bin/swaylock lock
+permit __PREFIX__/bin/swaybar panel
+permit __PREFIX__/bin/swaybg background
+permit __PREFIX__/bin/swaygrab screenshot
+
+# Configures which IPC features are enabled
+ipc {
+ command enabled
+ outputs enabled
+ workspaces enabled
+ tree enabled
+ marks enabled
+ bar-config enabled
+ inputs enabled
+
+ events {
+ workspace enabled
+ output enabled
+ mode enabled
+ window enabled
+ input enabled
+ binding disabled
+ }
+}
+
+# Limits the contexts from which certain commands are permitted
+commands {
+ * all
+
+ fullscreen binding criteria
+ bindsym config
+ exit binding
+ kill binding
+}
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt
@@ -91,7 +91,7 @@ function(add_config name source destination)
endfunction()
add_config(config config sway)
-add_config(security config.d/security sway/config.d)
+add_config(security security sway)
add_manpage(sway 1)
add_manpage(sway 5)
diff --git a/sway/commands/commands.c b/sway/commands/commands.c
@@ -19,5 +19,10 @@ struct cmd_results *cmd_commands(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE, "commands", "Can only be used in config file.");
}
+ if (!current_config_path || strcmp(SYSCONFDIR "/sway/security", current_config_path) != 0) {
+ return cmd_results_new(CMD_INVALID, "permit",
+ "This command is only permitted to run from " SYSCONFDIR "/sway/security");
+ }
+
return cmd_results_new(CMD_BLOCK_COMMANDS, NULL, NULL);
}
diff --git a/sway/commands/ipc.c b/sway/commands/ipc.c
@@ -21,6 +21,11 @@ struct cmd_results *cmd_ipc(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file.");
}
+ if (!current_config_path || strcmp(SYSCONFDIR "/sway/security", current_config_path) != 0) {
+ return cmd_results_new(CMD_INVALID, "permit",
+ "This command is only permitted to run from " SYSCONFDIR "/sway/security");
+ }
+
return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL);
}
diff --git a/sway/commands/permit.c b/sway/commands/permit.c
@@ -64,6 +64,11 @@ struct cmd_results *cmd_permit(int argc, char **argv) {
return error;
}
+ if (!current_config_path || strcmp(SYSCONFDIR "/sway/security", current_config_path) != 0) {
+ return cmd_results_new(CMD_INVALID, "permit",
+ "This command is only permitted to run from " SYSCONFDIR "/sway/security");
+ }
+
struct feature_policy *policy = get_policy(argv[0]);
policy->features |= get_features(argc, argv, &error);
@@ -83,6 +88,11 @@ struct cmd_results *cmd_reject(int argc, char **argv) {
return error;
}
+ if (!current_config_path || strcmp(SYSCONFDIR "/sway/security", current_config_path) != 0) {
+ return cmd_results_new(CMD_INVALID, "permit",
+ "This command is only permitted to run from " SYSCONFDIR "/sway/security");
+ }
+
struct feature_policy *policy = get_policy(argv[0]);
policy->features &= ~get_features(argc, argv, &error);
diff --git a/sway/config.c b/sway/config.c
@@ -452,8 +452,11 @@ static char *get_config_path(void) {
return NULL; // Not reached
}
+const char *current_config_path;
+
static bool load_config(const char *path, struct sway_config *config) {
sway_log(L_INFO, "Loading config from %s", path);
+ current_config_path = path;
struct stat sb;
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
@@ -474,11 +477,11 @@ static bool load_config(const char *path, struct sway_config *config) {
bool config_load_success = read_config(f, config);
fclose(f);
-
if (!config_load_success) {
sway_log(L_ERROR, "Error(s) loading config!");
}
+ current_config_path = NULL;
return true;
}
@@ -509,7 +512,8 @@ bool load_main_config(const char *file, bool is_active) {
list_add(config->config_chain, path);
config->reading = true;
- bool success = load_config(path, config);
+ bool success = load_config(SYSCONFDIR "/sway/security", config);
+ success = success && load_config(path, config);
if (is_active) {
config->reloading = false;
diff --git a/sway/main.c b/sway/main.c
@@ -179,37 +179,6 @@ static void security_sanity_check() {
"!! DANGER !! " SYSCONFDIR "/sway is not secure! It should be owned by root and set to 0755 at the minimum");
}
}
- struct {
- char *command;
- enum command_context context;
- bool checked;
- } expected[] = {
- { "reload", CONTEXT_BINDING, false },
- { "permit", CONTEXT_CONFIG, false },
- { "reject", CONTEXT_CONFIG, false },
- { "ipc", CONTEXT_CONFIG, false },
- };
- int expected_len = 4;
- for (int i = 0; i < config->command_policies->length; ++i) {
- struct command_policy *policy = config->command_policies->items[i];
- for (int j = 0; j < expected_len; ++j) {
- if (strcmp(expected[j].command, policy->command) == 0) {
- expected[j].checked = true;
- if (expected[j].context != policy->context) {
- sway_log(L_ERROR,
- "!! DANGER !! Command security policy for %s should be set to %s",
- expected[j].command, command_policy_str(expected[j].context));
- }
- }
- }
- }
- for (int j = 0; j < expected_len; ++j) {
- if (!expected[j].checked) {
- sway_log(L_ERROR,
- "!! DANGER !! Command security policy for %s should be set to %s",
- expected[j].command, command_policy_str(expected[j].context));
- }
- }
}
int main(int argc, char **argv) {
diff --git a/sway/sway-security.7.txt b/sway/sway-security.7.txt
@@ -19,22 +19,8 @@ usually best suited to a distro maintainer who wants to ship a secure sway
environment in their distro. Sway provides a number of means of securing it but
you must make a few changes external to sway first.
-Configuration security
-----------------------
-
-Many of Sway's security features are configurable. It's important that a possibly
-untrusted program is not able to edit this. Security rules are kept in
-_/etc/sway/config.d/security_ (usually), which should only be writable by root.
-However, configuration of security rules is not limited to this file - any config
-file that sway loads (including i.e. _~/.config/sway/config_) should not be editable
-by the user you intend to run programs as. One simple strategy is to use
-/etc/sway/config instead of a config file in your home directory, but that doesn't
-work well for multi-user systems. A more robust strategy is to run untrusted
-programs as another user, or in a sandbox. Configuring this is up to you.
-
-Note that _/etc/sway/config.d/*_ must be included explicitly from your config file.
-This is done by default in /etc/sway/config but you must check your own config if
-you choose to place it in other locations.
+Security-related configuration is only valid in /etc/sway/config (or whatever path
+is appropriate for your system).
Environment security
--------------------