mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Add ipc connection feature policy controls
This commit is contained in:
		
							parent
							
								
									62dad7148f
								
							
						
					
					
						commit
						d353da248b
					
				
					 6 changed files with 34 additions and 10 deletions
				
			
		| 
						 | 
					@ -202,6 +202,7 @@ enum secure_feature {
 | 
				
			||||||
	FEATURE_FULLSCREEN = 16,
 | 
						FEATURE_FULLSCREEN = 16,
 | 
				
			||||||
	FEATURE_KEYBOARD = 32,
 | 
						FEATURE_KEYBOARD = 32,
 | 
				
			||||||
	FEATURE_MOUSE = 64,
 | 
						FEATURE_MOUSE = 64,
 | 
				
			||||||
 | 
						FEATURE_IPC = 128,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct feature_policy {
 | 
					struct feature_policy {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -542,16 +542,15 @@ struct cmd_results *config_commands_command(char *exec) {
 | 
				
			||||||
		{ "criteria", CONTEXT_CRITERIA },
 | 
							{ "criteria", CONTEXT_CRITERIA },
 | 
				
			||||||
		{ "all", CONTEXT_ALL },
 | 
							{ "all", CONTEXT_ALL },
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	size_t names_len = 5;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (int i = 1; i < argc; ++i) {
 | 
						for (int i = 1; i < argc; ++i) {
 | 
				
			||||||
		size_t j;
 | 
							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) {
 | 
								if (strcmp(context_names[j].name, argv[i]) == 0) {
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (j == names_len) {
 | 
							if (j == sizeof(context_names) / sizeof(context_names[0])) {
 | 
				
			||||||
			results = cmd_results_new(CMD_INVALID, cmd,
 | 
								results = cmd_results_new(CMD_INVALID, cmd,
 | 
				
			||||||
					"Invalid command context %s", argv[i]);
 | 
										"Invalid command context %s", argv[i]);
 | 
				
			||||||
			goto cleanup;
 | 
								goto cleanup;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,17 +19,17 @@ static enum secure_feature get_features(int argc, char **argv,
 | 
				
			||||||
		{ "fullscreen", FEATURE_FULLSCREEN },
 | 
							{ "fullscreen", FEATURE_FULLSCREEN },
 | 
				
			||||||
		{ "keyboard", FEATURE_KEYBOARD },
 | 
							{ "keyboard", FEATURE_KEYBOARD },
 | 
				
			||||||
		{ "mouse", FEATURE_MOUSE },
 | 
							{ "mouse", FEATURE_MOUSE },
 | 
				
			||||||
 | 
							{ "ipc", FEATURE_IPC },
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	size_t names_len = 7;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (int i = 1; i < argc; ++i) {
 | 
						for (int i = 1; i < argc; ++i) {
 | 
				
			||||||
		size_t j;
 | 
							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) {
 | 
								if (strcmp(feature_names[j].name, argv[i]) == 0) {
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (j == names_len) {
 | 
							if (j == sizeof(feature_names) / sizeof(feature_names[0])) {
 | 
				
			||||||
			*error = cmd_results_new(CMD_INVALID,
 | 
								*error = cmd_results_new(CMD_INVALID,
 | 
				
			||||||
					"permit", "Invalid feature grant %s", argv[i]);
 | 
										"permit", "Invalid feature grant %s", argv[i]);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include <libinput.h>
 | 
					#include <libinput.h>
 | 
				
			||||||
#include "sway/ipc-json.h"
 | 
					#include "sway/ipc-json.h"
 | 
				
			||||||
#include "sway/ipc-server.h"
 | 
					#include "sway/ipc-server.h"
 | 
				
			||||||
 | 
					#include "sway/security.h"
 | 
				
			||||||
#include "sway/config.h"
 | 
					#include "sway/config.h"
 | 
				
			||||||
#include "sway/commands.h"
 | 
					#include "sway/commands.h"
 | 
				
			||||||
#include "sway/input.h"
 | 
					#include "sway/input.h"
 | 
				
			||||||
| 
						 | 
					@ -124,6 +125,17 @@ struct sockaddr_un *ipc_user_sockaddr(void) {
 | 
				
			||||||
	return ipc_sockaddr;
 | 
						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) {
 | 
					int ipc_handle_connection(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
	(void) fd; (void) data;
 | 
						(void) fd; (void) data;
 | 
				
			||||||
	sway_log(L_DEBUG, "Event on IPC listening socket");
 | 
						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;
 | 
							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));
 | 
						struct ipc_client* client = malloc(sizeof(struct ipc_client));
 | 
				
			||||||
	client->payload_length = 0;
 | 
						client->payload_length = 0;
 | 
				
			||||||
	client->fd = client_fd;
 | 
						client->fd = client_fd;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
struct feature_policy *alloc_feature_policy(const char *program) {
 | 
					struct feature_policy *alloc_feature_policy(const char *program) {
 | 
				
			||||||
	struct feature_policy *policy = malloc(sizeof(struct feature_policy));
 | 
						struct feature_policy *policy = malloc(sizeof(struct feature_policy));
 | 
				
			||||||
	policy->program = strdup(program);
 | 
						policy->program = strdup(program);
 | 
				
			||||||
	policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE;
 | 
						policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE | FEATURE_IPC;
 | 
				
			||||||
	return policy;
 | 
						return policy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,9 @@ policies. These features are:
 | 
				
			||||||
	Permission to become fullscreen. Note that users can always make a window
 | 
						Permission to become fullscreen. Note that users can always make a window
 | 
				
			||||||
	fullscreen themselves with the fullscreen command.
 | 
						fullscreen themselves with the fullscreen command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**ipc**::
 | 
				
			||||||
 | 
						Permission to connect to sway's IPC socket.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**keyboard**::
 | 
					**keyboard**::
 | 
				
			||||||
	Permission to receive keyboard events (only while they are focused).
 | 
						Permission to receive keyboard events (only while they are focused).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,9 +101,9 @@ policies. These features are:
 | 
				
			||||||
**screenshot**::
 | 
					**screenshot**::
 | 
				
			||||||
	Permission to take screenshots or record the screen.
 | 
						Permission to take screenshots or record the screen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
By default, all programs are granted **fullscreen**, **keyboard**, and **mouse**
 | 
					By default, all programs are granted **fullscreen**, **keyboard**, **mouse**, and
 | 
				
			||||||
permissions. You can use the following config commands to control a program's
 | 
					**ipc** permissions. You can use the following config commands to control a
 | 
				
			||||||
access:
 | 
					program's access:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**permit** <executable> <features...>::
 | 
					**permit** <executable> <features...>::
 | 
				
			||||||
	Permits <executable> to use <features> (each feature seperated by a space).
 | 
						Permits <executable> to use <features> (each feature seperated by a space).
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue