[Xcb] new SELinux protocol reply problem

Xavier Toth txtoth at gmail.com
Fri Feb 23 11:07:30 PST 2007


I've defined a new protocol GetPropertyContext which I modeled after
GetAtomName in xproto.xml but it isn't quite working. Using the code
I've include in this message the call to
xcb_se_linux_get_property_context_reply in my test client never
returns which implies that the client never received the reply or the
full reply. At one point I did try setting the reply length to zero
and got a reply but the 'context' string returned only contained 20 of
41 bytes sent. What was also curious about this was that as I was
debugging and rooting around I could see in the connection in that the
entire context string had been received from the server. Is this just
a matter of setting the reply length correctly, if so what should I be
setting to and why? Also as I look at examples in xproto.xml many
requests and replies have a lot of padding that I don't understand the
need for can you help me understand why this is necessary?


XCB Protocol

<xcb header="xselinux" extension-xname="SELinux" extension-name="SELinux"
    major-version="1" minor-version="0">
    <import>xproto</import>

  <request name="ChangePropertyContext" opcode="0">
    <field type="WINDOW" name="window" />
    <field type="ATOM" name="property" />
    <field type="CARD16" name="context_len" />
    <list type="char" name="context">
      <fieldref>context_len</fieldref>
    </list>
  </request>

  <request name="GetPropertyContext" opcode="1">
    <field type="WINDOW" name="window" />
    <field type="ATOM" name="property" />
    <reply>
      <pad bytes="1" />
      <field type="CARD16" name="context_len" />
      <list type="CARD8" name="context">
        <fieldref>context_len</fieldref>
      </list>
    </reply>
  </request>

</xcb>

Server GetPropertyContext proc.

int
ProcGetPropertyContext(ClientPtr client)
{
    PropertyPtr pProp, prevProp;
    unsigned long len, rc;
    WindowPtr pWin;
    xcb_se_linux_get_property_context_reply_t reply;
    Mask access_mode = DixReadAccess;
    REQUEST(xcb_se_linux_get_property_context_request_t);
    security_context_t ctx;

    REQUEST_SIZE_MATCH(xcb_se_linux_get_property_context_request_t);
    rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
    if (rc != Success)
	return rc;

    if (!ValidAtom(stuff->property))
    {
	client->errorValue = stuff->property;
	return(BadAtom);
    }

    /* Find the property */
    pProp = wUserProps (pWin);
    prevProp = (PropertyPtr)NULL;
    while (pProp)
    {
	if (pProp->propertyName == stuff->property)
	    break;
	prevProp = pProp;
	pProp = pProp->next;
    }

    if (!pProp)
	return NullPropertyContextReply(client, &reply);

    switch (XaceHook(XACE_PROPERTY_ACCESS, client, pWin, stuff->property,
		     access_mode))
    {
    case XaceErrorOperation:
	client->errorValue = stuff->property;
	return BadAtom;;
    case XaceIgnoreOperation:
	return NullPropertyContextReply(client, &reply);
    }

    /*
     *  Return context value to client
     */
    rc = avc_sid_to_context(PropertyGetSIDPriv(pProp), &ctx);
    if (rc < 0) {
      FatalError("XSELinux: Failed to get security context!\n");
    }

    len = strlen(ctx);
    reply.response_type = X_Reply;
    reply.length = (len + 3) >> 2;
    reply.sequence = client->sequence;
    reply.context_len = len;

    WriteToClient(client,
sizeof(xcb_se_linux_get_property_context_reply_t), &reply);

    if (len > 0)
    {
	WriteToClient(client, len, (char *)ctx);
    }

    freecon(ctx);
    return(client->noClientException);
}

Test code.


#include <stdio.h>

#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xselinux.h>


int
main ()
{

  xcb_connection_t *c;
  xcb_screen_t     *screen;
  xcb_window_t      win;
  char             *title = "Hello World !";
  char             *title_icon = "Hello World ! (iconified)";

  xcb_generic_error_t *generic_error = NULL;

  xcb_intern_atom_cookie_t atom_cookie;
  xcb_intern_atom_reply_t *atom_reply;
  xcb_atom_t atom;
  xcb_get_atom_name_cookie_t atom_name_cookie;
  xcb_get_atom_name_reply_t *atom_name_reply;

  xcb_se_linux_get_property_context_cookie_t prop_cookie;
  xcb_se_linux_get_property_context_reply_t *prop_reply;


  /* Open the connection to the X server */
  c = xcb_connect (NULL, NULL);

  /* Get the first screen */
  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;

  /* Ask for our window's Id */
  win = xcb_generate_id (c);

  /* Create the window */
  xcb_create_window (c,                             /* Connection          */
                     0,                             /* depth               */
                     win,                           /* window Id           */
                     screen->root,                  /* parent window       */
                     0, 0,                          /* x, y                */
                     250, 150,                      /* width, height       */
                     10,                            /* border_width        */
                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                     screen->root_visual,           /* visual              */
                     0, NULL);                      /* masks, not used     */

  /* Set the title of the window */
  xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                       WM_NAME, STRING, 8,
                       strlen (title), title);

  /* Set the title of the window icon */
  xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                       WM_ICON_NAME, STRING, 8,
                       strlen(title_icon), title_icon);

  /* Map the window on the screen */
  xcb_map_window (c, win);

  xcb_flush (c);

  atom = xcb_intern_atom_reply (c,
                                      xcb_intern_atom (c,
                                                       0,
                                                       strlen("WM_NAME"),
                                                       "WM_NAME"),
                                      NULL)->atom;

  atom_name_cookie = xcb_get_atom_name(c, atom);
  atom_name_reply = xcb_get_atom_name_reply(c, atom_name_cookie,
&generic_error);
  fprintf(stderr, "atom %d %s\n",
xcb_get_atom_name_name_length(atom_name_reply),
(char*)xcb_get_atom_name_name(atom_name_reply));

  fprintf(stderr, "xcb_se_linux_get_property_context_reply_t %d\n",
sizeof(xcb_se_linux_get_property_context_reply_t));
  prop_cookie = xcb_se_linux_get_property_context(c, win, WM_NAME);
  prop_reply = xcb_se_linux_get_property_context_reply(c, prop_cookie,
&generic_error);

  if ((generic_error != NULL) || (prop_reply == NULL)) {
    free(generic_error);
    return 0;
  }

  int num_ret = xcb_se_linux_get_property_context_context_length(prop_reply);
  char *retval = xcb_se_linux_get_property_context_context(prop_reply);

  fprintf(stderr, "Context %d %s %d\n", num_ret, retval, strlen(retval));

  while (1) {}


  return 0;
}


More information about the Xcb mailing list