mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
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)
This commit is contained in:
parent
4e70cddf1d
commit
a2bf4ce96e
5 changed files with 38 additions and 53 deletions
|
|
@ -48,12 +48,12 @@ struct impl {
|
||||||
struct spa_hook module_listener;
|
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];
|
char path[2048];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
sprintf(path, "/proc/%u/cmdline", ucred->pid);
|
sprintf(path, "/proc/%u/cmdline", pid);
|
||||||
|
|
||||||
fd = open(path, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
|
@ -73,13 +73,13 @@ static int check_cmdline(struct pw_client *client, const struct ucred *ucred, co
|
||||||
return 0;
|
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];
|
char root_path[2048];
|
||||||
int root_fd, info_fd, res;
|
int root_fd, info_fd, res;
|
||||||
struct stat stat_buf;
|
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);
|
root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
|
||||||
if (root_fd == -1) {
|
if (root_fd == -1) {
|
||||||
/* Not able to open the root dir shouldn't happen. Probably the app died and
|
/* 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)
|
core_check_access(void *data, struct pw_client *client)
|
||||||
{
|
{
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
const struct ucred *ucred;
|
|
||||||
struct pw_permission permissions[1];
|
struct pw_permission permissions[1];
|
||||||
struct spa_dict_item items[2];
|
struct spa_dict_item items[2];
|
||||||
|
const struct pw_properties *props;
|
||||||
const char *str;
|
const char *str;
|
||||||
int res;
|
int pid, res;
|
||||||
|
|
||||||
ucred = pw_client_get_ucred(client);
|
pid = -EINVAL;
|
||||||
if (!ucred) {
|
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");
|
pw_log_info("no trusted pid found, assuming not sandboxed\n");
|
||||||
goto granted;
|
goto granted;
|
||||||
} else {
|
} 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) {
|
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)
|
if (res == 0)
|
||||||
goto granted;
|
goto granted;
|
||||||
if (res > 0)
|
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) {
|
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)
|
if (res == 0)
|
||||||
goto granted;
|
goto granted;
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
|
@ -153,7 +157,7 @@ core_check_access(void *data, struct pw_client *client)
|
||||||
goto wait_permissions;
|
goto wait_permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = check_flatpak(client, ucred);
|
res = check_flatpak(client, pid);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
pw_log_warn("module %p: client %p sandbox check failed: %s",
|
pw_log_warn("module %p: client %p sandbox check failed: %s",
|
||||||
|
|
|
||||||
|
|
@ -251,24 +251,32 @@ static struct pw_client *client_new(struct server *s, int fd)
|
||||||
struct pw_protocol *protocol = s->this.protocol;
|
struct pw_protocol *protocol = s->this.protocol;
|
||||||
struct protocol_data *pd = protocol->user_data;
|
struct protocol_data *pd = protocol->user_data;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
struct ucred ucred, *ucredp;
|
struct ucred ucred;
|
||||||
struct pw_core *core = protocol->core;
|
struct pw_core *core = protocol->core;
|
||||||
struct pw_properties *props;
|
struct pw_properties *props;
|
||||||
|
char buffer[1024];
|
||||||
len = sizeof(ucred);
|
|
||||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
|
|
||||||
pw_log_error("no peercred: %m");
|
|
||||||
ucredp = NULL;
|
|
||||||
} else {
|
|
||||||
ucredp = &ucred;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = pw_properties_new(PW_CLIENT_PROP_PROTOCOL, "protocol-native", NULL);
|
props = pw_properties_new(PW_CLIENT_PROP_PROTOCOL, "protocol-native", NULL);
|
||||||
if (props == NULL)
|
if (props == NULL)
|
||||||
goto exit;
|
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,
|
client = pw_client_new(protocol->core,
|
||||||
ucredp,
|
|
||||||
props,
|
props,
|
||||||
sizeof(struct client_data));
|
sizeof(struct client_data));
|
||||||
if (client == NULL)
|
if (client == NULL)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <spa/pod/parser.h>
|
#include <spa/pod/parser.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,6 @@ static const struct pw_core_events core_events = {
|
||||||
*/
|
*/
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
struct pw_client *pw_client_new(struct pw_core *core,
|
struct pw_client *pw_client_new(struct pw_core *core,
|
||||||
struct ucred *ucred,
|
|
||||||
struct pw_properties *properties,
|
struct pw_properties *properties,
|
||||||
size_t user_data_size)
|
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);
|
pw_log_debug("client %p: new", this);
|
||||||
|
|
||||||
this->core = core;
|
this->core = core;
|
||||||
if ((this->ucred_valid = (ucred != NULL)))
|
|
||||||
this->ucred = *ucred;
|
|
||||||
|
|
||||||
if (properties == NULL)
|
if (properties == NULL)
|
||||||
properties = pw_properties_new(NULL, NULL);
|
properties = pw_properties_new(NULL, NULL);
|
||||||
if (properties == NULL)
|
if (properties == NULL)
|
||||||
return 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);
|
pw_array_init(&impl->permissions, 1024);
|
||||||
p = pw_array_add(&impl->permissions, sizeof(struct pw_permission));
|
p = pw_array_add(&impl->permissions, sizeof(struct pw_permission));
|
||||||
p->id = SPA_ID_INVALID;
|
p->id = SPA_ID_INVALID;
|
||||||
|
|
@ -370,15 +361,6 @@ const struct pw_properties *pw_client_get_properties(struct pw_client *client)
|
||||||
return client->properties;
|
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
|
SPA_EXPORT
|
||||||
void *pw_client_get_user_data(struct pw_client *client)
|
void *pw_client_get_user_data(struct pw_client *client)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _GNU_SOURCE
|
|
||||||
#ifndef __USE_GNU
|
|
||||||
#define __USE_GNU
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <spa/utils/hook.h>
|
#include <spa/utils/hook.h>
|
||||||
|
|
||||||
/** \class pw_client
|
/** \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_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_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_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. */
|
/** Create a new client. This is mainly used by protocols. */
|
||||||
struct pw_client *
|
struct pw_client *
|
||||||
pw_client_new(struct pw_core *core, /**< the core object */
|
pw_client_new(struct pw_core *core, /**< the core object */
|
||||||
struct ucred *ucred, /**< optional ucred */
|
|
||||||
struct pw_properties *properties, /**< client properties */
|
struct pw_properties *properties, /**< client properties */
|
||||||
size_t user_data_size /**< extra user data size */);
|
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 */
|
/** Get the global associated with this client */
|
||||||
struct pw_global *pw_client_get_global(struct pw_client *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 */
|
/** listen to events from this client */
|
||||||
void pw_client_add_listener(struct pw_client *client,
|
void pw_client_add_listener(struct pw_client *client,
|
||||||
struct spa_hook *listener,
|
struct spa_hook *listener,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue