commit
5778c59a2f
@ -0,0 +1,52 @@
|
|||||||
|
# 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
|
||||||
|
modifier 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
|
||||||
|
restart binding
|
||||||
|
permit config
|
||||||
|
reject config
|
||||||
|
ipc config
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _SWAY_SECURITY_H
|
||||||
|
#define _SWAY_SECURITY_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "sway/config.h"
|
||||||
|
|
||||||
|
enum secure_feature get_feature_policy(pid_t pid);
|
||||||
|
enum command_context get_command_policy(const char *cmd);
|
||||||
|
|
||||||
|
const char *command_policy_str(enum command_context context);
|
||||||
|
|
||||||
|
struct feature_policy *alloc_feature_policy(const char *program);
|
||||||
|
struct command_policy *alloc_command_policy(const char *command);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_commands(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "commands", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "{") != 0) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "commands", "Expected block declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config->reading) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "commands", "Can only be used in config file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_BLOCK_COMMANDS, NULL, NULL);
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_ipc(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->reading && strcmp("{", argv[0]) != 0) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "ipc",
|
||||||
|
"Expected '{' at start of IPC config definition.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config->reading) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_ipc_events(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "events", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->reading && strcmp("{", argv[0]) != 0) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "events",
|
||||||
|
"Expected '{' at start of IPC event config definition.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config->reading) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "events", "Can only be used in config file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_BLOCK_IPC_EVENTS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_ipc_cmd(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enabled;
|
||||||
|
if (strcmp(argv[0], "enabled") == 0) {
|
||||||
|
enabled = true;
|
||||||
|
} else if (strcmp(argv[0], "disabled") == 0) {
|
||||||
|
enabled = false;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, argv[-1],
|
||||||
|
"Argument must be one of 'enabled' or 'disabled'");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
enum ipc_feature type;
|
||||||
|
} types[] = {
|
||||||
|
{ "command", IPC_FEATURE_COMMAND },
|
||||||
|
{ "workspaces", IPC_FEATURE_GET_WORKSPACES },
|
||||||
|
{ "outputs", IPC_FEATURE_GET_OUTPUTS },
|
||||||
|
{ "tree", IPC_FEATURE_GET_TREE },
|
||||||
|
{ "marks", IPC_FEATURE_GET_MARKS },
|
||||||
|
{ "bar-config", IPC_FEATURE_GET_BAR_CONFIG },
|
||||||
|
{ "inputs", IPC_FEATURE_GET_INPUTS },
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t type = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
|
||||||
|
if (strcmp(types[i].name, argv[-1]) == 0) {
|
||||||
|
type = types[i].type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
config->ipc_policy |= type;
|
||||||
|
sway_log(L_DEBUG, "Enabled IPC %s feature", argv[-1]);
|
||||||
|
} else {
|
||||||
|
config->ipc_policy &= ~type;
|
||||||
|
sway_log(L_DEBUG, "Disabled IPC %s feature", argv[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enabled;
|
||||||
|
if (strcmp(argv[0], "enabled") == 0) {
|
||||||
|
enabled = true;
|
||||||
|
} else if (strcmp(argv[0], "disabled") == 0) {
|
||||||
|
enabled = false;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, argv[-1],
|
||||||
|
"Argument must be one of 'enabled' or 'disabled'");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
enum ipc_feature type;
|
||||||
|
} types[] = {
|
||||||
|
{ "workspace", IPC_FEATURE_EVENT_WORKSPACE },
|
||||||
|
{ "output", IPC_FEATURE_EVENT_OUTPUT },
|
||||||
|
{ "mode", IPC_FEATURE_EVENT_MODE },
|
||||||
|
{ "window", IPC_FEATURE_EVENT_WINDOW },
|
||||||
|
{ "binding", IPC_FEATURE_EVENT_BINDING },
|
||||||
|
{ "input", IPC_FEATURE_EVENT_INPUT },
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t type = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
|
||||||
|
if (strcmp(types[i].name, argv[-1]) == 0) {
|
||||||
|
type = types[i].type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
config->ipc_policy |= type;
|
||||||
|
sway_log(L_DEBUG, "Enabled IPC %s event", argv[-1]);
|
||||||
|
} else {
|
||||||
|
config->ipc_policy &= ~type;
|
||||||
|
sway_log(L_DEBUG, "Disabled IPC %s event", argv[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/security.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static enum secure_feature get_features(int argc, char **argv,
|
||||||
|
struct cmd_results **error) {
|
||||||
|
enum secure_feature features = 0;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
enum secure_feature feature;
|
||||||
|
} feature_names[] = {
|
||||||
|
{ "lock", FEATURE_LOCK },
|
||||||
|
{ "panel", FEATURE_PANEL },
|
||||||
|
{ "background", FEATURE_BACKGROUND },
|
||||||
|
{ "screenshot", FEATURE_SCREENSHOT },
|
||||||
|
{ "fullscreen", FEATURE_FULLSCREEN },
|
||||||
|
{ "keyboard", FEATURE_KEYBOARD },
|
||||||
|
{ "mouse", FEATURE_MOUSE },
|
||||||
|
{ "ipc", FEATURE_IPC },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
size_t 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 == sizeof(feature_names) / sizeof(feature_names[0])) {
|
||||||
|
*error = cmd_results_new(CMD_INVALID,
|
||||||
|
"permit", "Invalid feature grant %s", argv[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
features |= feature_names[j].feature;
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct feature_policy *get_policy(const char *name) {
|
||||||
|
struct feature_policy *policy = NULL;
|
||||||
|
for (int i = 0; i < config->feature_policies->length; ++i) {
|
||||||
|
struct feature_policy *p = config->feature_policies->items[i];
|
||||||
|
if (strcmp(p->program, name) == 0) {
|
||||||
|
policy = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!policy) {
|
||||||
|
policy = alloc_feature_policy(name);
|
||||||
|
list_add(config->feature_policies, policy);
|
||||||
|
}
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_permit(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "permit", EXPECTED_MORE_THAN, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct feature_policy *policy = get_policy(argv[0]);
|
||||||
|
policy->features |= get_features(argc, argv, &error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(L_DEBUG, "Permissions granted to %s for features %d",
|
||||||
|
policy->program, policy->features);
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_reject(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "reject", EXPECTED_MORE_THAN, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct feature_policy *policy = get_policy(argv[0]);
|
||||||
|
policy->features &= ~get_features(argc, argv, &error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(L_DEBUG, "Permissions granted to %s for features %d",
|
||||||
|
policy->program, policy->features);
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/security.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
struct feature_policy *alloc_feature_policy(const char *program) {
|
||||||
|
uint32_t default_policy = 0;
|
||||||
|
for (int i = 0; i < config->feature_policies->length; ++i) {
|
||||||
|
struct feature_policy *policy = config->feature_policies->items[i];
|
||||||
|
if (strcmp(policy->program, "*") == 0) {
|
||||||
|
default_policy = policy->features;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct feature_policy *policy = malloc(sizeof(struct feature_policy));
|
||||||
|
policy->program = strdup(program);
|
||||||
|
policy->features = default_policy;
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct command_policy *alloc_command_policy(const char *command) {
|
||||||
|
struct command_policy *policy = malloc(sizeof(struct command_policy));
|
||||||
|
policy->command = strdup(command);
|
||||||
|
policy->context = 0;
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum secure_feature get_feature_policy(pid_t pid) {
|
||||||
|
const char *fmt = "/proc/%d/exe";
|
||||||
|
int pathlen = snprintf(NULL, 0, fmt, pid);
|
||||||
|
char *path = malloc(pathlen + 1);
|
||||||
|
snprintf(path, pathlen + 1, fmt, pid);
|
||||||
|
static char link[2048];
|
||||||
|
|
||||||
|
uint32_t default_policy = 0;
|
||||||
|
|
||||||
|
ssize_t len = readlink(path, link, sizeof(link));
|
||||||
|
if (len < 0) {
|
||||||
|
sway_log(L_INFO,
|
||||||
|
"WARNING: unable to read %s for security check. Using default policy.",
|
||||||
|
path);
|
||||||
|
strcpy(link, "*");
|
||||||
|
} else {
|
||||||
|
link[len] = '\0';
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
for (int i = 0; i < config->feature_policies->length; ++i) {
|
||||||
|
struct feature_policy *policy = config->feature_policies->items[i];
|
||||||
|
if (strcmp(policy->program, "*") == 0) {
|
||||||
|
default_policy = policy->features;
|
||||||
|
}
|
||||||
|
if (strcmp(policy->program, link) == 0) {
|
||||||
|
return policy->features;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum command_context get_command_policy(const char *cmd) {
|
||||||
|
uint32_t default_policy = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < config->command_policies->length; ++i) {
|
||||||
|
struct command_policy *policy = config->command_policies->items[i];
|
||||||
|
if (strcmp(policy->command, "*") == 0) {
|
||||||
|
default_policy = policy->context;
|
||||||
|
}
|
||||||
|
if (strcmp(policy->command, cmd) == 0) {
|
||||||
|
return policy->context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *command_policy_str(enum command_context context) {
|
||||||
|
switch (context) {
|
||||||
|
case CONTEXT_ALL:
|
||||||
|
return "all";
|
||||||
|
case CONTEXT_CONFIG:
|
||||||
|
return "config";
|
||||||
|
case CONTEXT_BINDING:
|
||||||
|
return "binding";
|
||||||
|
case CONTEXT_IPC:
|
||||||
|
return "IPC";
|
||||||
|
case CONTEXT_CRITERIA:
|
||||||
|
return "criteria";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,250 @@
|
|||||||
|
/////
|
||||||
|
vim:set ts=4 sw=4 tw=82 noet:
|
||||||
|
/////
|
||||||
|
sway-security (7)
|
||||||
|
=================
|
||||||
|
|
||||||
|
Name
|
||||||
|
----
|
||||||
|
sway-security - Guidelines for securing your sway install
|
||||||
|
|
||||||
|
Security Overview
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
**Sway is NOT secure**. We are working on it but do not trust that we have it all
|
||||||
|
figured out yet. The following man page is provisional.
|
||||||
|
|
||||||
|
Securing sway requires careful configuration of your environment, the sort that's
|
||||||
|
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.
|
||||||
|
|
||||||
|
Environment security
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
LD_PRELOAD is a mechanism designed to ruin the security of your system. There are
|
||||||
|
a number of strategies for dealing with this but they all suck a little. In order
|
||||||
|
of most practical to least practical:
|
||||||
|
|
||||||
|
1. Only run important programs via exec. Sway's exec command will ensure that
|
||||||
|
LD_PRELOAD is unset when running programs.
|
||||||
|
|
||||||
|
2. Remove LD_PRELOAD support from your dynamic loader (requires patching libc).
|
||||||
|
This may break programs that rely on LD_PRELOAD for legitimate functionality,
|
||||||
|
but this is the most effective solution.
|
||||||
|
|
||||||
|
3. Use static linking for important programs. Of course statically linked programs
|
||||||
|
are unaffected by the dynamic linking security dumpster fire.
|
||||||
|
|
||||||
|
Note that should you choose method 1, you MUST ensure that sway itself isn't
|
||||||
|
compromised by LD_PRELOAD. It probably isn't, but you can be sure by setting
|
||||||
|
/usr/bin/sway to a+s (setuid), which will instruct the dynamic linker not to
|
||||||
|
permit LD_PRELOAD for it (and will also run it as root, which sway will shortly
|
||||||
|
drop). You could also statically link sway itself.
|
||||||
|
|
||||||
|
Note that LD_LIBRARY_PATH has all of the same problems, and all of the same
|
||||||
|
solutions.
|
||||||
|
|
||||||
|
Read your log
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Sway does sanity checks and prints big red warnings to stderr if they fail. Read
|
||||||
|
them.
|
||||||
|
|
||||||
|
Feature policies
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Certain sway features are security sensitive and may be configured with security
|
||||||
|
policies. These features are:
|
||||||
|
|
||||||
|
**background**::
|
||||||
|
Permission for a program to become the background.
|
||||||
|
|
||||||
|
**fullscreen**::
|
||||||
|
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).
|
||||||
|
|
||||||
|
**lock**::
|
||||||
|
Permission for a program to act as a screen locker. This involves becoming
|
||||||
|
fullscreen (on all outputs) and receiving _all_ keyboard and mouse input for
|
||||||
|
the duration of the process.
|
||||||
|
|
||||||
|
**mouse**::
|
||||||
|
Permission to receive mouse events (only while the mouse is over them).
|
||||||
|
|
||||||
|
**panel**::
|
||||||
|
Permission for a program to stick its windows to the sides of the screen.
|
||||||
|
|
||||||
|
**screenshot**::
|
||||||
|
Permission to take screenshots or record the screen.
|
||||||
|
|
||||||
|
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** <executable> <features...>::
|
||||||
|
Permits <executable> to use <features> (each feature seperated by a space).
|
||||||
|
<executable> may be * to affect the default policy, or the full path to the
|
||||||
|
executable file.
|
||||||
|
|
||||||
|
**reject** <executable> <features...>::
|
||||||
|
Disallows <executable> from using <features> (each feature seperated by a space).
|
||||||
|
<executable> may be * to affect the default policy, or the full path to the
|
||||||
|
executable file.
|
||||||
|
|
||||||
|
Note that policy enforcement requires procfs to be mounted at /proc and the sway
|
||||||
|
process to be able to access _/proc/[pid]/exe_ (see **procfs(5)** for details on
|
||||||
|
this access - setcap cap_sys_ptrace=eip /usr/bin/sway should do the trick). If
|
||||||
|
sway is unable to read _/proc/[pid]/exe_, it will apply the default policy.
|
||||||
|
|
||||||
|
To work correctly, sway's own programs require the following permissions:
|
||||||
|
|
||||||
|
- swaybg: background
|
||||||
|
- swaylock: lock, keyboard
|
||||||
|
- swaybar: panel, mouse, ipc
|
||||||
|
- swaygrab: screenshot, ipc
|
||||||
|
|
||||||
|
When you first declare a policy for an executable, it will inherit the default
|
||||||
|
policy. Further changes to the default policy will not retroactively affect which
|
||||||
|
permissions an earlier policy inherits. You must explicitly reject any features
|
||||||
|
from the default policy that you do not want an executable to receive permission
|
||||||
|
for.
|
||||||
|
|
||||||
|
Command policies
|
||||||
|
----------------
|
||||||
|
|
||||||
|
You can also control the context from which a command may execute. The different
|
||||||
|
contexts you can control are:
|
||||||
|
|
||||||
|
**config**::
|
||||||
|
Can be run from your config file.
|
||||||
|
|
||||||
|
**binding**::
|
||||||
|
Can be run from bindsym or bindcode commands.
|
||||||
|
|
||||||
|
**ipc**::
|
||||||
|
Can be run by IPC clients.
|
||||||
|
|
||||||
|
**criteria**::
|
||||||
|
Can be run when evaluating window criteria.
|
||||||
|
|
||||||
|
**all**::
|
||||||
|
Shorthand for granting permission in all contexts.
|
||||||
|
|
||||||
|
By default a command is allowed to execute in any context. To configure this, open
|
||||||
|
a commands block and fill it with policies:
|
||||||
|
|
||||||
|
commands {
|
||||||
|
<name> <contexts...>
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
For example, you could do this to limit the use of the focus command to just
|
||||||
|
binding and critiera:
|
||||||
|
|
||||||
|
commands {
|
||||||
|
focus binding criteria
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting a command policy overwrites any previous policy that was in place.
|
||||||
|
|
||||||
|
IPC policies
|
||||||
|
------------
|
||||||
|
|
||||||
|
You may whitelist IPC access like so:
|
||||||
|
|
||||||
|
permit /usr/bin/swaybar ipc
|
||||||
|
permit /usr/bin/swaygrab ipc
|
||||||
|
# etc
|
||||||
|
|
||||||
|
Note that it's suggested you do not enable swaymsg to access IPC if you intend to
|
||||||
|
secure your IPC socket, because any program could just run swaymsg itself instead
|
||||||
|
of connecting to IPC directly.
|
||||||
|
|
||||||
|
You can also configure which features of IPC are available with an IPC block:
|
||||||
|
|
||||||
|
ipc {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The following commands are available within this block:
|
||||||
|
|
||||||
|
**bar-config** <enabled|disabled>::
|
||||||
|
Controls GET_BAR_CONFIG (required for swaybar to work at all).
|
||||||
|
|
||||||
|
**command** <enabled|disabled>::
|
||||||
|
Controls executing sway commands via IPC.
|
||||||
|
|
||||||
|
**inputs** <enabled|disabled>::
|
||||||
|
Controls GET_INPUTS (input device information).
|
||||||
|
|
||||||
|
**marks** <enabled|disabled>::
|
||||||
|
Controls GET_MARKS.
|
||||||
|
|
||||||
|
**outputs** <enabled|disabled>::
|
||||||
|
Controls GET_OUTPUTS.
|
||||||
|
|
||||||
|
**tree** <enabled|disabled>::
|
||||||
|
Controls GET_TREE.
|
||||||
|
|
||||||
|
**workspaces** <enabled|disabled>::
|
||||||
|
Controls GET_WORKSPACES.
|
||||||
|
|
||||||
|
You can also control which IPC events can be raised with an events block:
|
||||||
|
|
||||||
|
ipc {
|
||||||
|
events {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The following commands are vaild within an ipc events block:
|
||||||
|
|
||||||
|
**binding** <enabled|disabled>::
|
||||||
|
Controls keybinding notifications (disabled by default).
|
||||||
|
|
||||||
|
**input** <enabled|disabled>::
|
||||||
|
Controls input device hotplugging notifications.
|
||||||
|
|
||||||
|
**mode** <enabled|disabled>::
|
||||||
|
Controls output hotplugging notifications.
|
||||||
|
|
||||||
|
**output** <enabled|disabled>::
|
||||||
|
Controls output hotplugging notifications.
|
||||||
|
|
||||||
|
**window** <enabled|disabled>::
|
||||||
|
Controls window event notifications.
|
||||||
|
|
||||||
|
**workspace** <enabled|disabled>::
|
||||||
|
Controls workspace notifications.
|
||||||
|
|
||||||
|
Disabling some of these may cause swaybar to behave incorrectly.
|
||||||
|
|
||||||
|
Authors
|
||||||
|
-------
|
||||||
|
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
|
||||||
|
source contributors. For more information about sway development, see
|
||||||
|
<https://github.com/SirCmpwn/sway>.
|
Loading…
Reference in new issue