LCOV - code coverage report
Current view: top level - login - logind-session-device.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 276 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 17 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 208 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <fcntl.h>
       4                 :            : #include <linux/input.h>
       5                 :            : #include <string.h>
       6                 :            : #include <sys/ioctl.h>
       7                 :            : #include <sys/types.h>
       8                 :            : 
       9                 :            : #include "sd-device.h"
      10                 :            : #include "sd-daemon.h"
      11                 :            : 
      12                 :            : #include "alloc-util.h"
      13                 :            : #include "bus-util.h"
      14                 :            : #include "fd-util.h"
      15                 :            : #include "logind-session-dbus.h"
      16                 :            : #include "logind-session-device.h"
      17                 :            : #include "missing.h"
      18                 :            : #include "parse-util.h"
      19                 :            : #include "util.h"
      20                 :            : 
      21                 :            : enum SessionDeviceNotifications {
      22                 :            :         SESSION_DEVICE_RESUME,
      23                 :            :         SESSION_DEVICE_TRY_PAUSE,
      24                 :            :         SESSION_DEVICE_PAUSE,
      25                 :            :         SESSION_DEVICE_RELEASE,
      26                 :            : };
      27                 :            : 
      28                 :          0 : static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
      29                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
      30                 :          0 :         _cleanup_free_ char *path = NULL;
      31                 :          0 :         const char *t = NULL;
      32                 :            :         uint32_t major, minor;
      33                 :            :         int r;
      34                 :            : 
      35         [ #  # ]:          0 :         assert(sd);
      36                 :            : 
      37                 :          0 :         major = major(sd->dev);
      38                 :          0 :         minor = minor(sd->dev);
      39                 :            : 
      40         [ #  # ]:          0 :         if (!sd->session->controller)
      41                 :          0 :                 return 0;
      42                 :            : 
      43                 :          0 :         path = session_bus_path(sd->session);
      44         [ #  # ]:          0 :         if (!path)
      45                 :          0 :                 return -ENOMEM;
      46                 :            : 
      47         [ #  # ]:          0 :         r = sd_bus_message_new_signal(
      48                 :          0 :                         sd->session->manager->bus,
      49                 :            :                         &m, path,
      50                 :            :                         "org.freedesktop.login1.Session",
      51                 :            :                         (type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice");
      52         [ #  # ]:          0 :         if (!m)
      53                 :          0 :                 return r;
      54                 :            : 
      55                 :          0 :         r = sd_bus_message_set_destination(m, sd->session->controller);
      56         [ #  # ]:          0 :         if (r < 0)
      57                 :          0 :                 return r;
      58                 :            : 
      59   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
      60                 :            : 
      61                 :          0 :         case SESSION_DEVICE_RESUME:
      62                 :          0 :                 r = sd_bus_message_append(m, "uuh", major, minor, sd->fd);
      63         [ #  # ]:          0 :                 if (r < 0)
      64                 :          0 :                         return r;
      65                 :          0 :                 break;
      66                 :            : 
      67                 :          0 :         case SESSION_DEVICE_TRY_PAUSE:
      68                 :          0 :                 t = "pause";
      69                 :          0 :                 break;
      70                 :            : 
      71                 :          0 :         case SESSION_DEVICE_PAUSE:
      72                 :          0 :                 t = "force";
      73                 :          0 :                 break;
      74                 :            : 
      75                 :          0 :         case SESSION_DEVICE_RELEASE:
      76                 :          0 :                 t = "gone";
      77                 :          0 :                 break;
      78                 :            : 
      79                 :          0 :         default:
      80                 :          0 :                 return -EINVAL;
      81                 :            :         }
      82                 :            : 
      83         [ #  # ]:          0 :         if (t) {
      84                 :          0 :                 r = sd_bus_message_append(m, "uus", major, minor, t);
      85         [ #  # ]:          0 :                 if (r < 0)
      86                 :          0 :                         return r;
      87                 :            :         }
      88                 :            : 
      89                 :          0 :         return sd_bus_send(sd->session->manager->bus, m, NULL);
      90                 :            : }
      91                 :            : 
      92                 :          0 : static void sd_eviocrevoke(int fd) {
      93                 :            :         static bool warned = false;
      94                 :            : 
      95         [ #  # ]:          0 :         assert(fd >= 0);
      96                 :            : 
      97         [ #  # ]:          0 :         if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
      98                 :            : 
      99   [ #  #  #  # ]:          0 :                 if (errno == EINVAL && !warned) {
     100         [ #  # ]:          0 :                         log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
     101                 :          0 :                         warned = true;
     102                 :            :                 }
     103                 :            :         }
     104                 :          0 : }
     105                 :            : 
     106                 :          0 : static int sd_drmsetmaster(int fd) {
     107         [ #  # ]:          0 :         assert(fd >= 0);
     108                 :            : 
     109         [ #  # ]:          0 :         if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0)
     110                 :          0 :                 return -errno;
     111                 :            : 
     112                 :          0 :         return 0;
     113                 :            : }
     114                 :            : 
     115                 :          0 : static int sd_drmdropmaster(int fd) {
     116         [ #  # ]:          0 :         assert(fd >= 0);
     117                 :            : 
     118         [ #  # ]:          0 :         if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0)
     119                 :          0 :                 return -errno;
     120                 :            : 
     121                 :          0 :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :          0 : static int session_device_open(SessionDevice *sd, bool active) {
     125                 :            :         int fd, r;
     126                 :            : 
     127         [ #  # ]:          0 :         assert(sd);
     128         [ #  # ]:          0 :         assert(sd->type != DEVICE_TYPE_UNKNOWN);
     129         [ #  # ]:          0 :         assert(sd->node);
     130                 :            : 
     131                 :            :         /* open device and try to get an udev_device from it */
     132                 :          0 :         fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
     133         [ #  # ]:          0 :         if (fd < 0)
     134                 :          0 :                 return -errno;
     135                 :            : 
     136      [ #  #  # ]:          0 :         switch (sd->type) {
     137                 :            : 
     138                 :          0 :         case DEVICE_TYPE_DRM:
     139         [ #  # ]:          0 :                 if (active) {
     140                 :            :                         /* Weird legacy DRM semantics might return an error even though we're master. No way to detect
     141                 :            :                          * that so fail at all times and let caller retry in inactive state. */
     142                 :          0 :                         r = sd_drmsetmaster(fd);
     143         [ #  # ]:          0 :                         if (r < 0) {
     144                 :          0 :                                 close_nointr(fd);
     145                 :          0 :                                 return r;
     146                 :            :                         }
     147                 :            :                 } else
     148                 :            :                         /* DRM-Master is granted to the first user who opens a device automatically (ughh,
     149                 :            :                          * racy!). Hence, we just drop DRM-Master in case we were the first. */
     150                 :          0 :                         (void) sd_drmdropmaster(fd);
     151                 :          0 :                 break;
     152                 :            : 
     153                 :          0 :         case DEVICE_TYPE_EVDEV:
     154         [ #  # ]:          0 :                 if (!active)
     155                 :          0 :                         sd_eviocrevoke(fd);
     156                 :          0 :                 break;
     157                 :            : 
     158                 :          0 :         case DEVICE_TYPE_UNKNOWN:
     159                 :            :         default:
     160                 :            :                 /* fallback for devices without synchronizations */
     161                 :          0 :                 break;
     162                 :            :         }
     163                 :            : 
     164                 :          0 :         return fd;
     165                 :            : }
     166                 :            : 
     167                 :          0 : static int session_device_start(SessionDevice *sd) {
     168                 :            :         int r;
     169                 :            : 
     170         [ #  # ]:          0 :         assert(sd);
     171         [ #  # ]:          0 :         assert(session_is_active(sd->session));
     172                 :            : 
     173         [ #  # ]:          0 :         if (sd->active)
     174                 :          0 :                 return 0;
     175                 :            : 
     176      [ #  #  # ]:          0 :         switch (sd->type) {
     177                 :            : 
     178                 :          0 :         case DEVICE_TYPE_DRM:
     179         [ #  # ]:          0 :                 if (sd->fd < 0)
     180         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EBADF),
     181                 :            :                                                "Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
     182                 :            : 
     183                 :            :                 /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
     184                 :            :                  * keep the device paused. Maybe at some point we have a drmStealMaster(). */
     185                 :          0 :                 r = sd_drmsetmaster(sd->fd);
     186         [ #  # ]:          0 :                 if (r < 0)
     187                 :          0 :                         return r;
     188                 :          0 :                 break;
     189                 :            : 
     190                 :          0 :         case DEVICE_TYPE_EVDEV:
     191                 :            :                 /* Evdev devices are revoked while inactive. Reopen it and we are fine. */
     192                 :          0 :                 r = session_device_open(sd, true);
     193         [ #  # ]:          0 :                 if (r < 0)
     194                 :          0 :                         return r;
     195                 :            : 
     196                 :            :                 /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
     197                 :            :                  * into a session and logind has been restarted right before. */
     198                 :          0 :                 safe_close(sd->fd);
     199                 :          0 :                 sd->fd = r;
     200                 :          0 :                 break;
     201                 :            : 
     202                 :          0 :         case DEVICE_TYPE_UNKNOWN:
     203                 :            :         default:
     204                 :            :                 /* fallback for devices without synchronizations */
     205                 :          0 :                 break;
     206                 :            :         }
     207                 :            : 
     208                 :          0 :         sd->active = true;
     209                 :          0 :         return 0;
     210                 :            : }
     211                 :            : 
     212                 :          0 : static void session_device_stop(SessionDevice *sd) {
     213         [ #  # ]:          0 :         assert(sd);
     214                 :            : 
     215         [ #  # ]:          0 :         if (!sd->active)
     216                 :          0 :                 return;
     217                 :            : 
     218      [ #  #  # ]:          0 :         switch (sd->type) {
     219                 :            : 
     220                 :          0 :         case DEVICE_TYPE_DRM:
     221         [ #  # ]:          0 :                 if (sd->fd < 0) {
     222         [ #  # ]:          0 :                         log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
     223                 :          0 :                         return;
     224                 :            :                 }
     225                 :            : 
     226                 :            :                 /* On DRM devices we simply drop DRM-Master but keep it open.
     227                 :            :                  * This allows the user to keep resources allocated. The
     228                 :            :                  * CAP_SYS_ADMIN restriction to DRM-Master prevents users from
     229                 :            :                  * circumventing this. */
     230                 :          0 :                 sd_drmdropmaster(sd->fd);
     231                 :          0 :                 break;
     232                 :            : 
     233                 :          0 :         case DEVICE_TYPE_EVDEV:
     234                 :            :                 /* Revoke access on evdev file-descriptors during deactivation.
     235                 :            :                  * This will basically prevent any operations on the fd and
     236                 :            :                  * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN
     237                 :            :                  * protection this way. */
     238                 :          0 :                 sd_eviocrevoke(sd->fd);
     239                 :          0 :                 break;
     240                 :            : 
     241                 :          0 :         case DEVICE_TYPE_UNKNOWN:
     242                 :            :         default:
     243                 :            :                 /* fallback for devices without synchronization */
     244                 :          0 :                 break;
     245                 :            :         }
     246                 :            : 
     247                 :          0 :         sd->active = false;
     248                 :            : }
     249                 :            : 
     250                 :          0 : static DeviceType detect_device_type(sd_device *dev) {
     251                 :            :         const char *sysname, *subsystem;
     252                 :          0 :         DeviceType type = DEVICE_TYPE_UNKNOWN;
     253                 :            : 
     254   [ #  #  #  # ]:          0 :         if (sd_device_get_sysname(dev, &sysname) < 0 ||
     255                 :          0 :             sd_device_get_subsystem(dev, &subsystem) < 0)
     256                 :          0 :                 return type;
     257                 :            : 
     258         [ #  # ]:          0 :         if (streq(subsystem, "drm")) {
     259         [ #  # ]:          0 :                 if (startswith(sysname, "card"))
     260                 :          0 :                         type = DEVICE_TYPE_DRM;
     261         [ #  # ]:          0 :         } else if (streq(subsystem, "input")) {
     262         [ #  # ]:          0 :                 if (startswith(sysname, "event"))
     263                 :          0 :                         type = DEVICE_TYPE_EVDEV;
     264                 :            :         }
     265                 :            : 
     266                 :          0 :         return type;
     267                 :            : }
     268                 :            : 
     269                 :          0 : static int session_device_verify(SessionDevice *sd) {
     270                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *p = NULL;
     271                 :            :         const char *sp, *node;
     272                 :            :         sd_device *dev;
     273                 :            :         int r;
     274                 :            : 
     275                 :          0 :         r = sd_device_new_from_devnum(&p, 'c', sd->dev);
     276         [ #  # ]:          0 :         if (r < 0)
     277                 :          0 :                 return r;
     278                 :            : 
     279                 :          0 :         dev = p;
     280                 :            : 
     281   [ #  #  #  # ]:          0 :         if (sd_device_get_syspath(dev, &sp) < 0 ||
     282                 :          0 :             sd_device_get_devname(dev, &node) < 0)
     283                 :          0 :                 return -EINVAL;
     284                 :            : 
     285                 :            :         /* detect device type so we can find the correct sysfs parent */
     286                 :          0 :         sd->type = detect_device_type(dev);
     287         [ #  # ]:          0 :         if (sd->type == DEVICE_TYPE_UNKNOWN)
     288                 :          0 :                 return -ENODEV;
     289                 :            : 
     290         [ #  # ]:          0 :         else if (sd->type == DEVICE_TYPE_EVDEV) {
     291                 :            :                 /* for evdev devices we need the parent node as device */
     292         [ #  # ]:          0 :                 if (sd_device_get_parent_with_subsystem_devtype(p, "input", NULL, &dev) < 0)
     293                 :          0 :                         return -ENODEV;
     294         [ #  # ]:          0 :                 if (sd_device_get_syspath(dev, &sp) < 0)
     295                 :          0 :                         return -ENODEV;
     296                 :            : 
     297         [ #  # ]:          0 :         } else if (sd->type != DEVICE_TYPE_DRM)
     298                 :            :                 /* Prevent opening unsupported devices. Especially devices of
     299                 :            :                  * subsystem "input" must be opened via the evdev node as
     300                 :            :                  * we require EVIOCREVOKE. */
     301                 :          0 :                 return -ENODEV;
     302                 :            : 
     303                 :            :         /* search for an existing seat device and return it if available */
     304                 :          0 :         sd->device = hashmap_get(sd->session->manager->devices, sp);
     305         [ #  # ]:          0 :         if (!sd->device) {
     306                 :            :                 /* The caller might have gotten the udev event before we were
     307                 :            :                  * able to process it. Hence, fake the "add" event and let the
     308                 :            :                  * logind-manager handle the new device. */
     309                 :          0 :                 r = manager_process_seat_device(sd->session->manager, dev);
     310         [ #  # ]:          0 :                 if (r < 0)
     311                 :          0 :                         return r;
     312                 :            : 
     313                 :            :                 /* if it's still not available, then the device is invalid */
     314                 :          0 :                 sd->device = hashmap_get(sd->session->manager->devices, sp);
     315         [ #  # ]:          0 :                 if (!sd->device)
     316                 :          0 :                         return -ENODEV;
     317                 :            :         }
     318                 :            : 
     319         [ #  # ]:          0 :         if (sd->device->seat != sd->session->seat)
     320                 :          0 :                 return -EPERM;
     321                 :            : 
     322                 :          0 :         sd->node = strdup(node);
     323         [ #  # ]:          0 :         if (!sd->node)
     324                 :          0 :                 return -ENOMEM;
     325                 :            : 
     326                 :          0 :         return 0;
     327                 :            : }
     328                 :            : 
     329                 :          0 : int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out) {
     330                 :            :         SessionDevice *sd;
     331                 :            :         int r;
     332                 :            : 
     333         [ #  # ]:          0 :         assert(s);
     334         [ #  # ]:          0 :         assert(out);
     335                 :            : 
     336         [ #  # ]:          0 :         if (!s->seat)
     337                 :          0 :                 return -EPERM;
     338                 :            : 
     339                 :          0 :         sd = new0(SessionDevice, 1);
     340         [ #  # ]:          0 :         if (!sd)
     341                 :          0 :                 return -ENOMEM;
     342                 :            : 
     343                 :          0 :         sd->session = s;
     344                 :          0 :         sd->dev = dev;
     345                 :          0 :         sd->fd = -1;
     346                 :          0 :         sd->type = DEVICE_TYPE_UNKNOWN;
     347                 :            : 
     348                 :          0 :         r = session_device_verify(sd);
     349         [ #  # ]:          0 :         if (r < 0)
     350                 :          0 :                 goto error;
     351                 :            : 
     352                 :          0 :         r = hashmap_put(s->devices, &sd->dev, sd);
     353         [ #  # ]:          0 :         if (r < 0)
     354                 :          0 :                 goto error;
     355                 :            : 
     356         [ #  # ]:          0 :         if (open_device) {
     357                 :            :                 /* Open the device for the first time. We need a valid fd to pass back
     358                 :            :                  * to the caller. If the session is not active, this _might_ immediately
     359                 :            :                  * revoke access and thus invalidate the fd. But this is still needed
     360                 :            :                  * to pass a valid fd back. */
     361                 :          0 :                 sd->active = session_is_active(s);
     362                 :          0 :                 r = session_device_open(sd, sd->active);
     363         [ #  # ]:          0 :                 if (r < 0) {
     364                 :            :                         /* EINVAL _may_ mean a master is active; retry inactive */
     365   [ #  #  #  # ]:          0 :                         if (sd->active && r == -EINVAL) {
     366                 :          0 :                                 sd->active = false;
     367                 :          0 :                                 r = session_device_open(sd, false);
     368                 :            :                         }
     369         [ #  # ]:          0 :                         if (r < 0)
     370                 :          0 :                                 goto error;
     371                 :            :                 }
     372                 :          0 :                 sd->fd = r;
     373                 :            :         }
     374                 :            : 
     375   [ #  #  #  # ]:          0 :         LIST_PREPEND(sd_by_device, sd->device->session_devices, sd);
     376                 :            : 
     377                 :          0 :         *out = sd;
     378                 :          0 :         return 0;
     379                 :            : 
     380                 :          0 : error:
     381                 :          0 :         hashmap_remove(s->devices, &sd->dev);
     382                 :          0 :         free(sd->node);
     383                 :          0 :         free(sd);
     384                 :          0 :         return r;
     385                 :            : }
     386                 :            : 
     387                 :          0 : void session_device_free(SessionDevice *sd) {
     388         [ #  # ]:          0 :         assert(sd);
     389                 :            : 
     390                 :            :         /* Make sure to remove the pushed fd. */
     391         [ #  # ]:          0 :         if (sd->pushed_fd)
     392                 :          0 :                 (void) sd_notifyf(false,
     393                 :            :                                   "FDSTOREREMOVE=1\n"
     394                 :            :                                   "FDNAME=session-%s-device-%u-%u",
     395                 :          0 :                                   sd->session->id, major(sd->dev), minor(sd->dev));
     396                 :            : 
     397                 :          0 :         session_device_stop(sd);
     398                 :          0 :         session_device_notify(sd, SESSION_DEVICE_RELEASE);
     399                 :          0 :         safe_close(sd->fd);
     400                 :            : 
     401   [ #  #  #  #  :          0 :         LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
             #  #  #  # ]
     402                 :            : 
     403                 :          0 :         hashmap_remove(sd->session->devices, &sd->dev);
     404                 :            : 
     405                 :          0 :         free(sd->node);
     406                 :          0 :         free(sd);
     407                 :          0 : }
     408                 :            : 
     409                 :          0 : void session_device_complete_pause(SessionDevice *sd) {
     410                 :            :         SessionDevice *iter;
     411                 :            :         Iterator i;
     412                 :            : 
     413         [ #  # ]:          0 :         if (!sd->active)
     414                 :          0 :                 return;
     415                 :            : 
     416                 :          0 :         session_device_stop(sd);
     417                 :            : 
     418                 :            :         /* if not all devices are paused, wait for further completion events */
     419         [ #  # ]:          0 :         HASHMAP_FOREACH(iter, sd->session->devices, i)
     420         [ #  # ]:          0 :                 if (iter->active)
     421                 :          0 :                         return;
     422                 :            : 
     423                 :            :         /* complete any pending session switch */
     424                 :          0 :         seat_complete_switch(sd->session->seat);
     425                 :            : }
     426                 :            : 
     427                 :          0 : void session_device_resume_all(Session *s) {
     428                 :            :         SessionDevice *sd;
     429                 :            :         Iterator i;
     430                 :            : 
     431         [ #  # ]:          0 :         assert(s);
     432                 :            : 
     433         [ #  # ]:          0 :         HASHMAP_FOREACH(sd, s->devices, i) {
     434         [ #  # ]:          0 :                 if (sd->active)
     435                 :          0 :                         continue;
     436                 :            : 
     437         [ #  # ]:          0 :                 if (session_device_start(sd) < 0)
     438                 :          0 :                         continue;
     439         [ #  # ]:          0 :                 if (session_device_save(sd) < 0)
     440                 :          0 :                         continue;
     441                 :            : 
     442                 :          0 :                 session_device_notify(sd, SESSION_DEVICE_RESUME);
     443                 :            :         }
     444                 :          0 : }
     445                 :            : 
     446                 :          0 : void session_device_pause_all(Session *s) {
     447                 :            :         SessionDevice *sd;
     448                 :            :         Iterator i;
     449                 :            : 
     450         [ #  # ]:          0 :         assert(s);
     451                 :            : 
     452         [ #  # ]:          0 :         HASHMAP_FOREACH(sd, s->devices, i) {
     453         [ #  # ]:          0 :                 if (!sd->active)
     454                 :          0 :                         continue;
     455                 :            : 
     456                 :          0 :                 session_device_stop(sd);
     457                 :          0 :                 session_device_notify(sd, SESSION_DEVICE_PAUSE);
     458                 :            :         }
     459                 :          0 : }
     460                 :            : 
     461                 :          0 : unsigned session_device_try_pause_all(Session *s) {
     462                 :          0 :         unsigned num_pending = 0;
     463                 :            :         SessionDevice *sd;
     464                 :            :         Iterator i;
     465                 :            : 
     466         [ #  # ]:          0 :         assert(s);
     467                 :            : 
     468         [ #  # ]:          0 :         HASHMAP_FOREACH(sd, s->devices, i) {
     469         [ #  # ]:          0 :                 if (!sd->active)
     470                 :          0 :                         continue;
     471                 :            : 
     472                 :          0 :                 session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
     473                 :          0 :                 num_pending++;
     474                 :            :         }
     475                 :            : 
     476                 :          0 :         return num_pending;
     477                 :            : }
     478                 :            : 
     479                 :          0 : int session_device_save(SessionDevice *sd) {
     480                 :          0 :         _cleanup_free_ char *m = NULL;
     481                 :            :         const char *id;
     482                 :            :         int r;
     483                 :            : 
     484         [ #  # ]:          0 :         assert(sd);
     485                 :            : 
     486                 :            :         /* Store device fd in PID1. It will send it back to us on restart so revocation will continue to work. To make
     487                 :            :          * things simple, send fds for all type of devices even if they don't support the revocation mechanism so we
     488                 :            :          * don't have to handle them differently later.
     489                 :            :          *
     490                 :            :          * Note: for device supporting revocation, PID1 will drop a stored fd automatically if the corresponding device
     491                 :            :          * is revoked. */
     492                 :            : 
     493         [ #  # ]:          0 :         if (sd->pushed_fd)
     494                 :          0 :                 return 0;
     495                 :            : 
     496                 :            :         /* Session ID does not contain separators. */
     497                 :          0 :         id = sd->session->id;
     498         [ #  # ]:          0 :         assert(*(id + strcspn(id, "-\n")) == '\0');
     499                 :            : 
     500                 :          0 :         r = asprintf(&m, "FDSTORE=1\n"
     501                 :            :                          "FDNAME=session-%s-device-%u-%u\n",
     502                 :            :                          id, major(sd->dev), minor(sd->dev));
     503         [ #  # ]:          0 :         if (r < 0)
     504                 :          0 :                 return r;
     505                 :            : 
     506                 :          0 :         r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
     507         [ #  # ]:          0 :         if (r < 0)
     508                 :          0 :                 return r;
     509                 :            : 
     510                 :          0 :         sd->pushed_fd = true;
     511                 :          0 :         return 1;
     512                 :            : }
     513                 :            : 
     514                 :          0 : void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
     515         [ #  # ]:          0 :         assert(fd >= 0);
     516         [ #  # ]:          0 :         assert(sd);
     517         [ #  # ]:          0 :         assert(sd->fd < 0);
     518         [ #  # ]:          0 :         assert(!sd->active);
     519                 :            : 
     520                 :          0 :         sd->fd = fd;
     521                 :          0 :         sd->pushed_fd = true;
     522                 :          0 :         sd->active = active;
     523                 :          0 : }

Generated by: LCOV version 1.14