Xnamespace: add selection isolation
Selection names (as seen by the client) are internally prefixed with the namespace ID, so each client can only access those within it's namespace. If a client within namespace "foo" want's to operate on "PRIMARY", it actually will be doing so on "<foo>PRIMARY", w/o ever noticing it. Events will sent back to the client still pointing to "PRIMARY". Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
parent
0698743fde
commit
5901cb001d
|
@ -0,0 +1,67 @@
|
|||
#define HOOK_NAME "selection"
|
||||
|
||||
#include <dix-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dix/selection_priv.h"
|
||||
|
||||
#include "namespace.h"
|
||||
#include "hooks.h"
|
||||
|
||||
static inline const char *stripNS(const char* name) {
|
||||
if ((!name) || (name[0] != '<'))
|
||||
return name; // can this ever happen ?
|
||||
const char *got = strchr(name, '>');
|
||||
if (!got)
|
||||
return name;
|
||||
return ++got;
|
||||
}
|
||||
|
||||
/*
|
||||
* This hook is rewriting the client visible selection names to internally used,
|
||||
* per namespace ones. Whenever a client is asking for a selection, it's name
|
||||
* is replaced by a namespaced one, e.g. asking for "PRIMARY" while being in
|
||||
* namespace "foo" will become "<foo>PRIMARY"
|
||||
*
|
||||
* A malicious client could still send specially crafted messages to others,
|
||||
* asking them to send their selection data to him. This needs to be solved
|
||||
* separately, by a send hook.
|
||||
*/
|
||||
void hookSelectionFilter(CallbackListPtr *pcbl, void *unused, void *calldata)
|
||||
{
|
||||
XNS_HOOK_HEAD(SelectionFilterParamRec);
|
||||
|
||||
/* no rewrite if client is in root namespace */
|
||||
if (subj->ns->superPower)
|
||||
return;
|
||||
|
||||
const char *origSelectionName = NameForAtom(param->selection);
|
||||
|
||||
char selname[PATH_MAX] = { 0 };
|
||||
snprintf(selname, sizeof(selname)-1, "<%s>%s", subj->ns->name, origSelectionName);
|
||||
Atom realSelection = MakeAtom(selname, strlen(selname), TRUE);
|
||||
|
||||
switch (param->op) {
|
||||
case SELECTION_FILTER_GETOWNER:
|
||||
case SELECTION_FILTER_SETOWNER:
|
||||
case SELECTION_FILTER_CONVERT:
|
||||
case SELECTION_FILTER_LISTEN:
|
||||
// TODO: check whether window really belongs to the client
|
||||
param->selection = realSelection;
|
||||
break;
|
||||
|
||||
case SELECTION_FILTER_NOTIFY:
|
||||
{
|
||||
// need to translate back, since we're having the ns-prefixed name here
|
||||
const char *stripped = stripNS(origSelectionName);
|
||||
param->selection = MakeAtom(stripped, strlen(stripped), TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
// nothing to do here: already having the client visible name
|
||||
case SELECTION_FILTER_EV_REQUEST:
|
||||
case SELECTION_FILTER_EV_CLEAR:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -25,5 +25,6 @@
|
|||
struct XnamespaceClientPriv *subj = XnsClientPriv(client);
|
||||
|
||||
void hookClientState(CallbackListPtr *pcbl, void *unused, void *calldata);
|
||||
void hookSelectionFilter(CallbackListPtr *pcbl, void *unused, void *calldata);
|
||||
|
||||
#endif /* __XSERVER_NAMESPACE_HOOKS_H */
|
||||
|
|
|
@ -3,6 +3,7 @@ libxserver_namespace = static_library(
|
|||
[
|
||||
'config.c',
|
||||
'hook-clientstate.c',
|
||||
'hook-selection.c',
|
||||
'namespace.c',
|
||||
],
|
||||
include_directories: inc,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <X11/Xmd.h>
|
||||
|
||||
#include "dix/dix_priv.h"
|
||||
#include "dix/selection_priv.h"
|
||||
#include "include/os.h"
|
||||
#include "miext/extinit_priv.h"
|
||||
|
||||
|
@ -27,7 +28,8 @@ NamespaceExtensionInit(void)
|
|||
|
||||
if (!(dixRegisterPrivateKey(&namespaceClientPrivKeyRec, PRIVATE_CLIENT,
|
||||
sizeof(struct XnamespaceClientPriv)) &&
|
||||
AddCallback(&ClientStateCallback, hookClientState, NULL)))
|
||||
AddCallback(&ClientStateCallback, hookClientState, NULL) &&
|
||||
AddCallback(&SelectionFilterCallback, hookSelectionFilter, NULL)))
|
||||
FatalError("NamespaceExtensionInit: allocation failure\n");
|
||||
|
||||
/* Do the serverClient */
|
||||
|
|
Loading…
Reference in New Issue