[PATCH 1/3] dix: Add facilities for client ID tracking.

Mark Kettenis mark.kettenis at xs4all.nl
Mon Aug 30 11:44:57 PDT 2010


> From: =?utf-8?q?Rami=20Ylim=C3=A4ki?= <rami.ylimaki at vincit.fi>
> Date: Mon, 30 Aug 2010 16:29:31 +0300
> 
> An interface is provided for figuring out the PID and process name of
> a client. Make some existing functionality from SELinux and IA
> extensions available for general use.

The problem is that the guts that implement this are rather
Linux-specific.  For example:

> +/* Try to determine a command line string for a client based on its
> + * PID. This should be called only once when a new client has
> + * connected, use GetClientCmd to determine the string at other
> + * times. Error (NULL) is returned if command line string can't be
> + * determined for the client. You must release the returned string by
> + * calling free when it's not used anymore. */
> +static const char *DetermineClientCmd(ClientPtr client, pid_t pid)
> +{
> +    char path[PATH_MAX + 1];
> +    char *cmd = NULL;
> +    int fd = 0;
> +    int bytes = 0;
> +
> +    if (client == NullClient)
> +        return NULL;
> +
> +    if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
> +        return NULL;
> +
> +    fd = open(path, O_RDONLY);
> +    if (fd < 0)
> +        return NULL;
> +    bytes = read(fd, path, sizeof(path));
> +    if (bytes <= 0)
> +        return NULL;
> +    if (close(fd) < 0)
> +        return NULL;
> +
> +    /* We are only interested in the process name. We don't care about
> +     * its arguments. Allocate space only for the process name. */
> +    path[bytes - 1] = '\0';
> +    bytes = strlen(path) + 1;
> +    cmd = malloc(bytes);
> +    if (cmd == NULL)
> +        return NULL;
> +    strncpy(cmd, path, bytes);
> +    cmd[bytes - 1] = '\0';
> +
> +    return cmd;
> +}

This relies on the OS having a /proc filesystem.  Not all OSes
implement such a thing, some don't have it enabled by default
(OpenBSD, where it's only used for Linux emulation) or have a very
different layout (Solaris).  OS-specific code should be cleary marked
as such and probably be moved to ../os

> +/* Try to determine a PID for a client from its connection
> + * information. This should be called only once when new client has
> + * connected, use GetClientPid to determine the PID at other
> + * times. Error (0) is returned if PID can't be determined for the
> + * client. */

Returning 0 in the error case is probably a bad idea, since I do
believe that on some systems, 0 is a valid process ID.  A better
choice would be (pid_t)-1, which is used for this purpose by setsid().

> +static pid_t DetermineClientPid(ClientPtr client)
> +{
> +    LocalClientCredRec *lcc = NULL;
> +    pid_t pid = 0;
> +
> +    if (client == NullClient)
> +        return 0;
> +
> +    if (client == serverClient)
> +        return getpid();
> +
> +    if (GetLocalClientCreds(client, &lcc) != -1)
> +    {
> +        if (lcc->fieldsSet & LCC_PID_SET)
> +            pid = lcc->pid;
> +        FreeLocalClientCreds(lcc);
> +    }
> +
> +    return pid;
> +}
> +


More information about the xorg-devel mailing list