[PATCH RFC] Xorg: Add a suid root wrapper

Hans de Goede hdegoede at redhat.com
Thu Mar 6 04:57:32 PST 2014


Hi,

Thanks for the review!

On 03/06/2014 01:46 PM, Mark Kettenis wrote:
>> From: Hans de Goede <hdegoede at redhat.com>
>> Date: Wed,  5 Mar 2014 16:51:52 +0100
> 
> If you end up going with this wrapper approach anyway despite my
> previous message, here are some comments.
> 
> Oh, and it's good that this is optional.
> 
>> diff --git a/hw/xfree86/Xorg.sh b/hw/xfree86/Xorg.sh
>> new file mode 100644
>> index 0000000..3a2b34b
>> --- /dev/null
>> +++ b/hw/xfree86/Xorg.sh
>> @@ -0,0 +1,13 @@
>> +#!/bin/sh
>> +#
>> +# See if Xorg.wrap is installed and if it is execute it, otherwise execute
>> +# Xorg.bin directly. This allows distros to put the suid wrapper in a
>> +# separate package.
>> +
>> +canonical=$(readlink -f "$0")
> 
> POSIX doesn't specify readlink(1), so it might not be available on all
> systems.  Solaris doesn't seem to have it.  Perhaps just have
> configure substitute the installation path here?

Yeah that seems like a good idea.

>> +basedir=$(dirname "$canonical")
>> +if [ -x "$basedir"/Xorg.wrap ]; then
>> +	exec "$basedir"/Xorg.wrap "$@"
>> +else
>> +	exec "$basedir"/Xorg.bin "$@"
>> +fi
> 
>> diff --git a/hw/xfree86/xorg-wrapper.c b/hw/xfree86/xorg-wrapper.c
>> new file mode 100644
>> index 0000000..93a5f15
>> --- /dev/null
>> +++ b/hw/xfree86/xorg-wrapper.c
>> @@ -0,0 +1,82 @@
>> +/*
>> + * Copyright © 2014 Red Hat, Inc.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> + * DEALINGS IN THE SOFTWARE.
>> + *
>> + * Author: Hans de Goede <hdegoede at redhat.com>
>> + */
>> +
>> +#include <fcntl.h>
>> +#include <limits.h>
>> +#include <stdint.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <sys/ioctl.h>
>> +#include <sys/stat.h>
>> +#include <sys/types.h>
>> +#include <unistd.h>
>> +#include <drm/drm.h>
>> +
>> +#include "dix-config.h" /* For PROJECTROOT */
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    struct drm_mode_card_res res;
>> +    char buf[PATH_MAX];
>> +    int i, r, fd;
>> +    int kms_cards = 0;
>> +    int total_cards = 0;
>> +
>> +    for (i = 0; i < 16; i++) {
>> +        snprintf(buf, PATH_MAX, "/dev/dri/card%d", i);
> 
> Hardcoding paths like this is a bad idea.  We use "/dev/drm%d" on
> OpenBSD for example.  Other systems might use different names yet
> again.

We may end up putting a define in some config.h for this, but ...

> Probably better to use libdrm.

Ugh no, this is a suid-root wrapper, less code is more here. Yes
I know libdrm is designed to be safe to run as root, but it is still
better to not run it as root at all.

>> +        fd = open(buf, O_RDWR);
>> +        if (fd == -1)
>> +            continue;
>> +
>> +        total_cards++;
>> +
>> +        memset(&res, 0, sizeof(struct drm_mode_card_res));
>> +        r = ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
>> +        if (r == 0 && res.count_connectors > 0)
>> +            kms_cards++;
>> +
>> +        close(fd);
>> +    }
>> +
>> +    /* If we've found cards, and all cards support kms, drop root rights */
>> +    if (total_cards && kms_cards == total_cards) {
> 
> I think total_cards only includes devices that have a kernel drm
> driver loaded.  So what you're really checking here is how many of
> those provide KMS support.  So you're missing any true legacy device.

That is why the check is there for if we've found any cards at all, so
on a machine with only a legacy card the wrapper will keep the root rights.

I admit that on a machine with 2 cards, one legacy one kms it may end up doing
the wrong thing. That is why the non RFC version of this patch is going to have
a /etc/X11/Xwrapper.config config file, so that people can simply put a

needs_root_rights = 1

In there, given that this is rather a corner case which will likely require
manual config anyways that seems like a better idea then complicating the
wrapper a lot for this corner case.

Regards,

Hans


More information about the xorg-devel mailing list