[systemd-devel] [PATCH v2 05/10] logind: introduce session-devices

Lennart Poettering lennart at poettering.net
Tue Sep 17 10:34:15 PDT 2013


On Tue, 17.09.13 17:39, David Herrmann (dh.herrmann at gmail.com) wrote:

>          "   <arg name=\"force\" type=\"b\"/>\n"                         \
>          "  </method>\n"                                                 \
>          "  <method name=\"DropControl\"/>\n"                            \
> +        "  <method name=\"RequestDevice\">\n"                           \
> +        "   <arg name=\"node\" type=\"s\" direction=\"in\"/>\n"         \
> +        "   <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n"          \
> +        "   <arg name=\"paused\" type=\"b\" direction=\"out\"/>\n"      \
> +        "  </method>\n"                                                 \
> +        "  <method name=\"ReleaseDevice\">\n"                           \
> +        "   <arg name=\"node\" type=\"s\"/>\n"                          \
> +        "  </method>\n"
>          \

Please rename this pair to TakeDevice() and ReleaseDevice().

> index 0000000..659f161
> --- /dev/null
> +++ b/src/login/logind-session-device.c
> @@ -0,0 +1,489 @@
> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
> +
> +/***
> +  This file is part of systemd.
> +
> +  Copyright 2013 David Herrmann
> +
> +  systemd is free software; you can redistribute it and/or modify it
> +  under the terms of the GNU Lesser General Public License as published by
> +  the Free Software Foundation; either version 2.1 of the License, or
> +  (at your option) any later version.
> +
> +  systemd is distributed in the hope that it will be useful, but
> +  WITHOUT ANY WARRANTY; without even the implied warranty of
> +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +  Lesser General Public License for more details.
> +
> +  You should have received a copy of the GNU Lesser General Public License
> +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +***/
> +
> +#include <assert.h>
> +#include <fcntl.h>
> +#include <libudev.h>
> +#include <linux/input.h>
> +#include <linux/ioctl.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +
> +#include "dbus-common.h"
> +#include "logind-session-device.h"
> +#include "util.h"
> +
> +enum SessionDeviceNotifications {
> +        SESSION_DEVICE_RESUME,
> +        SESSION_DEVICE_TRY_PAUSE,
> +        SESSION_DEVICE_PAUSE,
> +        SESSION_DEVICE_RELEASE,
> +};
> +
> +static void session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
> +        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
> +        _cleanup_free_ char *path = NULL;
> +        const char *t = NULL;
> +
> +        assert(sd);
> +
> +        if (!sd->session->controller)
> +                return;
> +
> +        path = session_bus_path(sd->session);
> +        if (!path)
> +                return;
> +
> +        m = dbus_message_new_signal(path,
> +                                    "org.freedesktop.login1.Session",
> +                                    (type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice");
> +        if (!m)
> +                return;
> +
> +        if (!dbus_message_set_destination(m, sd->session->controller))
> +                return;
> +
> +        switch (type) {
> +        case SESSION_DEVICE_RESUME:
> +                if (!dbus_message_append_args(m,
> +                                              DBUS_TYPE_STRING, &sd->node,
> +                                              DBUS_TYPE_UNIX_FD, &sd->fd,
> +                                              DBUS_TYPE_INVALID))
> +                        return;
> +                break;
> +        case SESSION_DEVICE_TRY_PAUSE:
> +                t = "pause";
> +                break;
> +        case SESSION_DEVICE_PAUSE:
> +                t = "force";
> +                break;
> +        case SESSION_DEVICE_RELEASE:
> +                t = "gone";
> +                break;
> +        default:
> +                return;
> +        }
> +
> +        if (t && !dbus_message_append_args(m,
> +                                           DBUS_TYPE_STRING, &sd->node,
> +                                           DBUS_TYPE_STRING, &t,
> +                                           DBUS_TYPE_INVALID))
> +                return;
> +
> +        dbus_connection_send(sd->session->manager->bus, m, NULL);
> +}
> +
> +static int sd_eviocrevoke(int fd)
> +{

"{" please on the same line as the function name.

> +        static bool warned;
> +        int r;
> +
> +#ifndef EVIOCREVOKE
> +#  define EVIOCREVOKE _IOW('E', 0x91, int)
> +#endif

Please move this to missing.h.

> +
> +        assert(fd >= 0);
> +
> +        r = ioctl(fd, EVIOCREVOKE, 1);
> +        if (r < 0) {
> +                r = -errno;
> +                if (r == -ENOSYS && !warned) {
> +                        warned = true;
> +                        log_warning("kernel does not support evdev-revocation");
> +                }
> +        }
> +
> +        return 0;
> +}
> +
> +static int sd_drmsetmaster(int fd)
> +{

"{"...

> +        int r;
> +
> +#ifndef DRM_IOCTL_SET_MASTER
> +#  define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
> +#endif

→ missing.h!

> +
> +        assert(fd >= 0);
> +
> +        r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
> +        if (r < 0)
> +                return -errno;
> +
> +        return 0;
> +}
> +
> +static int sd_drmdropmaster(int fd)
> +{

"{"....

> +        int r;
> +
> +#ifndef DRM_IOCTL_DROP_MASTER
> +#  define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
> +#endif

→ missing.h

> +        switch (sd->type) {
> +        case DEVICE_TYPE_DRM:
> +                if (active) {
> +                        sd_drmsetmaster(fd);
> +                } else {

Please remove "{}".


> +        dnum = udev_device_get_devnum(dev);
> +        sysname = udev_device_get_sysname(dev);
> +        type = DEVICE_TYPE_UNKNOWN;
> +
> +        if (major(dnum) == 29) {
> +                if (startswith(sysname, "fb"))
> +                        type = DEVICE_TYPE_FBDEV;
> +        } else if (major(dnum) == 226) {
> +                if (startswith(sysname, "card"))
> +                        type = DEVICE_TYPE_DRM;
> +        } else if (major(dnum) == 13) {
> +                if (startswith(sysname, "event"))
> +                        type = DEVICE_TYPE_EVDEV;

Please use udev_device_get_subsystem() for this! Comparing majors is evil!

> +        dev = udev_device_new_from_devnum(sd->session->manager->udev, 'c', st.st_rdev);
> +        if (!dev)
> +                return -ENODEV;
> +        sp = udev_device_get_syspath(dev);
> +
> +        /* Only allow access to "uaccess" tagged devices! */
> +        if (!udev_device_has_tag(dev, "uaccess")) {
> +                r = -EPERM;
> +                goto err_dev;
> +        }
> +

This sounds wrong, after all the suer could access the device directly
anyway if uaccess is set.

> +        /* Only allow opening the _real_ device node. This is the node provided
> +         * by devtmpfs! Issue a readlink() if you are not sure. We cannot allow
> +         * any path here as user-space could otherwise trigger OOM by requesting
> +         * duplicates. */
> +        real_node = udev_device_get_devnode(dev);
> +        if (!streq_ptr(real_node, node)) {
> +                r = -EINVAL;
> +                goto err_dev;
> +        }

I think it would make sense to drop this. Instead verify with
path_startswith() that the specified path is in /dev. Then do an lstat()
on the specified device path, and verify the backing major/minor matches
the one of /dev, so that people cannot use /dev/shm to confuse us.

> +typedef struct SessionDevice SessionDevice;
> +
> +#include "list.h"
> +#include "util.h"
> +#include "logind.h"
> +#include "logind-device.h"
> +#include "logind-seat.h"
> +#include "logind-session.h"
> +
> +enum DeviceType {
> +        DEVICE_TYPE_UNKNOWN,
> +        DEVICE_TYPE_FBDEV,
> +        DEVICE_TYPE_DRM,
> +        DEVICE_TYPE_EVDEV,
> +};

exported enums plese with a typdef!

Lennart

-- 
Lennart Poettering - Red Hat, Inc.


More information about the systemd-devel mailing list