From a2bf4ce96ef8a993dcd867d0eac75c35bba57b3f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 10 May 2019 13:12:22 +0200 Subject: [PATCH] protocol: add security label to a client Don't pass the ucred to the client construct, just set the properties in the protocol. Use the client properties to get ucred. Add the security label to the client properties (from SO_PEERSEC) --- src/modules/module-access.c | 30 +++++++++++-------- src/modules/module-protocol-native.c | 28 ++++++++++------- .../module-protocol-native/test-connection.c | 2 ++ src/pipewire/client.c | 18 ----------- src/pipewire/client.h | 13 +------- 5 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/modules/module-access.c b/src/modules/module-access.c index 5693b9b01..133f64fbc 100644 --- a/src/modules/module-access.c +++ b/src/modules/module-access.c @@ -48,12 +48,12 @@ struct impl { struct spa_hook module_listener; }; -static int check_cmdline(struct pw_client *client, const struct ucred *ucred, const char *str) +static int check_cmdline(struct pw_client *client, int pid, const char *str) { char path[2048]; int fd; - sprintf(path, "/proc/%u/cmdline", ucred->pid); + sprintf(path, "/proc/%u/cmdline", pid); fd = open(path, O_RDONLY); if (fd < 0) @@ -73,13 +73,13 @@ static int check_cmdline(struct pw_client *client, const struct ucred *ucred, co return 0; } -static int check_flatpak(struct pw_client *client, const struct ucred *ucred) +static int check_flatpak(struct pw_client *client, int pid) { char root_path[2048]; int root_fd, info_fd, res; struct stat stat_buf; - sprintf(root_path, "/proc/%u/root", ucred->pid); + sprintf(root_path, "/proc/%u/root", pid); root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); if (root_fd == -1) { /* Not able to open the root dir shouldn't happen. Probably the app died and @@ -113,23 +113,27 @@ static void core_check_access(void *data, struct pw_client *client) { struct impl *impl = data; - const struct ucred *ucred; struct pw_permission permissions[1]; struct spa_dict_item items[2]; + const struct pw_properties *props; const char *str; - int res; + int pid, res; - ucred = pw_client_get_ucred(client); - if (!ucred) { + pid = -EINVAL; + if ((props = pw_client_get_properties(client)) != NULL) { + if ((str = pw_properties_get(props, PW_CLIENT_PROP_UCRED_PID)) != NULL) + pid = atoi(str); + } + + if (pid < 0) { pw_log_info("no trusted pid found, assuming not sandboxed\n"); goto granted; } else { - pw_log_info("client has trusted pid %d", ucred->pid); + pw_log_info("client has trusted pid %d", pid); } - if (impl->properties && (str = pw_properties_get(impl->properties, "blacklisted")) != NULL) { - res = check_cmdline(client, ucred, str); + res = check_cmdline(client, pid, str); if (res == 0) goto granted; if (res > 0) @@ -139,7 +143,7 @@ core_check_access(void *data, struct pw_client *client) } if (impl->properties && (str = pw_properties_get(impl->properties, "restricted")) != NULL) { - res = check_cmdline(client, ucred, str); + res = check_cmdline(client, pid, str); if (res == 0) goto granted; if (res < 0) { @@ -153,7 +157,7 @@ core_check_access(void *data, struct pw_client *client) goto wait_permissions; } - res = check_flatpak(client, ucred); + res = check_flatpak(client, pid); if (res != 0) { if (res < 0) { pw_log_warn("module %p: client %p sandbox check failed: %s", diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c index e5ed6b627..6e3844956 100644 --- a/src/modules/module-protocol-native.c +++ b/src/modules/module-protocol-native.c @@ -251,24 +251,32 @@ static struct pw_client *client_new(struct server *s, int fd) struct pw_protocol *protocol = s->this.protocol; struct protocol_data *pd = protocol->user_data; socklen_t len; - struct ucred ucred, *ucredp; + struct ucred ucred; struct pw_core *core = protocol->core; struct pw_properties *props; - - len = sizeof(ucred); - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { - pw_log_error("no peercred: %m"); - ucredp = NULL; - } else { - ucredp = &ucred; - } + char buffer[1024]; props = pw_properties_new(PW_CLIENT_PROP_PROTOCOL, "protocol-native", NULL); if (props == NULL) goto exit; + len = sizeof(ucred); + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { + pw_log_error("no peercred: %m"); + } else { + pw_properties_setf(props, PW_CLIENT_PROP_UCRED_PID, "%d", ucred.pid); + pw_properties_setf(props, PW_CLIENT_PROP_UCRED_UID, "%d", ucred.uid); + pw_properties_setf(props, PW_CLIENT_PROP_UCRED_GID, "%d", ucred.gid); + } + + len = sizeof(buffer); + if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buffer, &len) < 0) { + pw_log_error("no peersec: %m"); + } else { + pw_properties_setf(props, PW_CLIENT_PROP_SEC_LABEL, "%s", buffer); + } + client = pw_client_new(protocol->core, - ucredp, props, sizeof(struct client_data)); if (client == NULL) diff --git a/src/modules/module-protocol-native/test-connection.c b/src/modules/module-protocol-native/test-connection.c index 7113aaf1b..eadc9efd7 100644 --- a/src/modules/module-protocol-native/test-connection.c +++ b/src/modules/module-protocol-native/test-connection.c @@ -22,6 +22,8 @@ * DEALINGS IN THE SOFTWARE. */ +#include + #include #include diff --git a/src/pipewire/client.c b/src/pipewire/client.c index 695374ddc..dbaa5fbf7 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -244,7 +244,6 @@ static const struct pw_core_events core_events = { */ SPA_EXPORT struct pw_client *pw_client_new(struct pw_core *core, - struct ucred *ucred, struct pw_properties *properties, size_t user_data_size) { @@ -260,20 +259,12 @@ struct pw_client *pw_client_new(struct pw_core *core, pw_log_debug("client %p: new", this); this->core = core; - if ((this->ucred_valid = (ucred != NULL))) - this->ucred = *ucred; if (properties == NULL) properties = pw_properties_new(NULL, NULL); if (properties == NULL) return NULL; - if (ucred) { - pw_properties_setf(properties, PW_CLIENT_PROP_UCRED_PID, "%d", ucred->pid); - pw_properties_setf(properties, PW_CLIENT_PROP_UCRED_UID, "%d", ucred->uid); - pw_properties_setf(properties, PW_CLIENT_PROP_UCRED_GID, "%d", ucred->gid); - } - pw_array_init(&impl->permissions, 1024); p = pw_array_add(&impl->permissions, sizeof(struct pw_permission)); p->id = SPA_ID_INVALID; @@ -370,15 +361,6 @@ const struct pw_properties *pw_client_get_properties(struct pw_client *client) return client->properties; } -SPA_EXPORT -const struct ucred *pw_client_get_ucred(struct pw_client *client) -{ - if (!client->ucred_valid) - return NULL; - - return &client->ucred; -} - SPA_EXPORT void *pw_client_get_user_data(struct pw_client *client) { diff --git a/src/pipewire/client.h b/src/pipewire/client.h index c60498d8f..f2e301cda 100644 --- a/src/pipewire/client.h +++ b/src/pipewire/client.h @@ -29,14 +29,6 @@ extern "C" { #endif -#ifdef _GNU_SOURCE -#ifndef __USE_GNU -#define __USE_GNU -#endif -#endif - -#include - #include /** \class pw_client @@ -124,11 +116,11 @@ struct pw_client_events { #define PW_CLIENT_PROP_UCRED_PID "pipewire.ucred.pid" /**< Client pid, set by protocol */ #define PW_CLIENT_PROP_UCRED_UID "pipewire.ucred.uid" /**< Client uid, set by protocol*/ #define PW_CLIENT_PROP_UCRED_GID "pipewire.ucred.gid" /**< client gid, set by protocol*/ +#define PW_CLIENT_PROP_SEC_LABEL "pipewire.sec.label" /**< client security label, set by protocol*/ /** Create a new client. This is mainly used by protocols. */ struct pw_client * pw_client_new(struct pw_core *core, /**< the core object */ - struct ucred *ucred, /**< optional ucred */ struct pw_properties *properties, /**< client properties */ size_t user_data_size /**< extra user data size */); @@ -169,9 +161,6 @@ struct pw_resource *pw_client_find_resource(struct pw_client *client, uint32_t i /** Get the global associated with this client */ struct pw_global *pw_client_get_global(struct pw_client *client); -/** Get the ucred from a client or NULL when not specified/valid */ -const struct ucred *pw_client_get_ucred(struct pw_client *client); - /** listen to events from this client */ void pw_client_add_listener(struct pw_client *client, struct spa_hook *listener,