Skip to content

Commit

Permalink
Working qrexec-policy-daemon
Browse files Browse the repository at this point in the history
Rewritten qrexec-daemon to use policy daemon instead of running
policy-exec separately for each call. If daemon fails, falls back
to old solution.

fixes QubesOS/qubes-issues#5125
  • Loading branch information
marmarta committed Dec 7, 2019
1 parent 666e8c5 commit b76a42f
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
script: pylint qrexec
- install: docker build -t qrexec-test ci
env: DOCKER_RUN="docker run -v $TRAVIS_BUILD_DIR:$TRAVIS_BUILD_DIR -v /tmp/.X11-unix:/tmp/.X11-unix -w $TRAVIS_BUILD_DIR -e DISPLAY=$DISPLAY -- qrexec-test"
script: $DOCKER_RUN python3 -m coverage run -m unittest discover -s qrexec/tests -t . -p '*.py' -v
script: $DOCKER_RUN python3 -m coverage run -m pytest qrexec/tests -o python_files=*.py -v
# - python: '3.7'
# script: python -m coverage run -m unittest discover -s qrexec/tests -t . -p '*.py' -v
- stage: deploy
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ install-dom0:
install -d $(DESTDIR)/etc/qubes/policy.d -m 775
install -d $(DESTDIR)/etc/qubes/policy.d/include -m 775
install -t $(DESTDIR)/etc/qubes/policy.d -m 664 policy.d/*
install -d $(DESTDIR)/lib/systemd/system -m 755
install -t $(DESTDIR)/lib/systemd/system -m 644 systemd/qubes-qrexec-policy-daemon.service
.PHONY: install-dom0


Expand All @@ -48,7 +50,7 @@ all-vm:
install-vm:
$(MAKE) install -C agent
install -d $(DESTDIR)/lib/systemd/system -m 755
install -t $(DESTDIR)/lib/systemd/system -m 644 systemd/*
install -t $(DESTDIR)/lib/systemd/system -m 644 systemd/qubes-qrexec-agent.service
install -m 0644 -D qubes-rpc-config/README $(DESTDIR)/etc/qubes/rpc-config/README
# install -d $(DESTDIR)/etc/qubes-rpc -m 755
# install -t $(DESTDIR)/etc/qubes-rpc -m 755 qubes-rpc/*
Expand Down
1 change: 1 addition & 0 deletions ci/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pylint
sphinx
codecov
pydbus
pytest-asyncio
84 changes: 84 additions & 0 deletions daemon/qrexec-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define _GNU_SOURCE

#include <sys/select.h>
#include <stdio.h>
Expand All @@ -28,12 +29,17 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <err.h>
#include <string.h>
#include <assert.h>
#include "qrexec.h"
#include "libqrexec-utils.h"

#define QREXEC_MIN_VERSION QREXEC_PROTOCOL_V2
#define QREXEC_SOCKET_PATH "/var/run/qubes/policy.sock"


enum client_state {
CLIENT_INVALID = 0, // table slot not used
Expand Down Expand Up @@ -678,6 +684,73 @@ static void sanitize_name(char * untrusted_s_signed, char *extra_allowed_chars)
* Called when agent sends a message asking to execute a predefined command.
*/

static int connect_daemon_socket(
const int remote_domain_id,
const char *remote_domain_name,
const char *target_domain,
const char *service_name,
const struct service_params *request_id
) {
int result;
int command_size;
char response[32];
char *command;
int daemon_socket;
struct sockaddr_un daemon_socket_address = {
.sun_family = AF_UNIX,
.sun_path = QREXEC_SOCKET_PATH
};

daemon_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (daemon_socket < 0) {
perror("socket creation failed");
return -1;
}

result = connect(daemon_socket, (struct sockaddr *) &daemon_socket_address,
sizeof(daemon_socket_address));
if (result < 0) {
perror("connection to socket failed");
return -1;
}

command_size = asprintf(&command, "domain_id=%d\n"
"source=%s\n"
"intended_target=%s\n"
"service_and_arg=%s\n"
"process_ident=%s\n\n",
remote_domain_id, remote_domain_name, target_domain,
service_name, request_id->ident);
if (command_size < 0) {
perror("failed to construct request");
return -1;
}

result = send(daemon_socket, command, command_size, 0);
free(command);
if (result < 0) {
perror("send to socket failed");
return -1;
}

result = recv(daemon_socket, response, sizeof(response), 0);
if (result < 0) {
perror("error reading from socket");
return -1;
}
else {
if (!strncmp(response, "result=allow\n", sizeof("result=allow\n")-1)) {
return 0;
} else if (!strncmp(response, "result=deny\n", sizeof("result=deny\n")-1)) {
return 1;
} else {
warnx("invalid response");
return -1;
}
}
}


static void handle_execute_service(
const int remote_domain_id,
const char *remote_domain_name,
Expand All @@ -686,6 +759,7 @@ static void handle_execute_service(
const struct service_params *request_id)
{
int i;
int result;
int policy_pending_slot;
pid_t pid;
char remote_domain_id_str[10];
Expand All @@ -708,6 +782,15 @@ static void handle_execute_service(
policy_pending[policy_pending_slot].params = *request_id;
return;
}

result = connect_daemon_socket(remote_domain_id, remote_domain_name,
target_domain, service_name, request_id);
if (result >= 0) {
_exit(result);
} else {
warnx("invalid response");
}

for (i = 3; i < MAX_FDS; i++)
close(i);
signal(SIGCHLD, SIG_DFL);
Expand All @@ -725,6 +808,7 @@ static void handle_execute_service(
_exit(1);
}


static void handle_connection_terminated()
{
struct exec_params untrusted_params, params;
Expand Down
1 change: 1 addition & 0 deletions debian/qubes-core-qrexec.install
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ usr/bin/qrexec-fork-server
usr/bin/qrexec-policy-graph
usr/bin/qrexec-policy-restore
usr/bin/qrexec-policy-exec
usr/bin/qrexec-policy-daemon
usr/bin/qrexec-policy
usr/bin/qrexec-policy-agent
usr/bin/qubes-policy
Expand Down
17 changes: 17 additions & 0 deletions rpm_spec/qubes-qrexec-dom0.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ export BACKEND_VMM=@BACKEND_VMM@
make all-dom0
#make -C doc PYTHON=%{__python3} SPHINXBUILD=sphinx-build-%{python3_version} man

%post
%systemd_post qubes-qrexec-policy-daemon.service

%preun
%systemd_preun qubes-qrexec-policy-daemon.service

%posttrans
# when upgrading from R4.0, %%postun of qubes-qrexec-policy-daemon will revert
# %%post of this package. Redo the action in %%posttrans
%systemd_post qubes-qrexec-policy-daemon.service
# and then start it back
if systemctl is-enabled qubes-qrexec-policy-daemon.service >/dev/null 2>&1; then
systemctl start qubes-qrexec-policy-daemon.service
fi

%install
make install-dom0 \
DESTDIR=$RPM_BUILD_ROOT \
Expand Down Expand Up @@ -96,5 +111,7 @@ rm -f %{name}-%{version}

%{_sysconfdir}/qubes-rpc/policy.RegisterArgument

/lib/systemd/system/qubes-qrexec-policy-daemon.service

%changelog
@CHANGELOG@
7 changes: 7 additions & 0 deletions systemd/qubes-qrexec-policy-daemon.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
Description=Qubes remote exec policy daemon
After=qubesd.service

[Service]
Type=simple
ExecStart=/usr/bin/qrexec-policy-daemon

0 comments on commit b76a42f

Please sign in to comment.