diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-04-02 11:52:58 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-04-02 11:52:58 +0200 |
commit | efc19ee4856f4dd5c47df466f3cc7f8496dd3c1a (patch) | |
tree | 00a430caa4876effbd45d7cc2f47f4ef1ec3f8fc | |
parent | 883d1b01b0d2ec0e396221ff0c977aec7f555ecf (diff) | |
download | systemd-efc19ee4856f4dd5c47df466f3cc7f8496dd3c1a.tar.gz |
logind: when we cannot attach a passed fd to a device, close it
Replaces: #8532
-rw-r--r-- | src/login/logind.c | 122 |
1 files changed, 61 insertions, 61 deletions
diff --git a/src/login/logind.c b/src/login/logind.c index c78994aae6..4c0e8ce6b1 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -378,73 +378,75 @@ static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) { return 0; } -static int manager_attach_fds(Manager *m) { - _cleanup_strv_free_ char **fdnames = NULL; - int n, i, fd; +static int deliver_fd(Manager *m, const char *fdname, int fd) { + _cleanup_free_ char *id = NULL; + SessionDevice *sd; + struct stat st; + Session *s; + dev_t dev; + int r; - /* Upon restart, PID1 will send us back all fds of session devices - * that we previously opened. Each file descriptor is associated - * with a given session. The session ids are passed through FDNAMES. */ + assert(m); + assert(fd >= 0); - n = sd_listen_fds_with_names(true, &fdnames); - if (n <= 0) - return n; - - for (i = 0; i < n; i++) { - _cleanup_free_ char *id = NULL; - dev_t dev; - struct stat st; - SessionDevice *sd; - Session *s; - int r; + r = parse_fdname(fdname, &id, &dev); + if (r < 0) + return log_debug_errno(r, "Failed to parse fd name %s: %m", fdname); - fd = SD_LISTEN_FDS_START + i; + s = hashmap_get(m->sessions, id); + if (!s) + /* If the session doesn't exist anymore, the associated session device attached to this fd + * doesn't either. Let's simply close this fd. */ + return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Failed to attach fd for unknown session: %s", id); - r = parse_fdname(fdnames[i], &id, &dev); - if (r < 0) { - log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]); - close_nointr(fd); - continue; - } + if (fstat(fd, &st) < 0) + /* The device is allowed to go away at a random point, in which case fstat() failing is + * expected. */ + return log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id); - s = hashmap_get(m->sessions, id); - if (!s) { - /* If the session doesn't exist anymore, the associated session - * device attached to this fd doesn't either. Let's simply close - * this fd. */ - log_debug("Failed to attach fd for unknown session: %s", id); - close_nointr(fd); - continue; - } + if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) + return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "Device fd doesn't point to the expected character device node"); - if (fstat(fd, &st) < 0) { - /* The device is allowed to go away at a random point, in which - * case fstat failing is expected. */ - log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id); - close_nointr(fd); - continue; - } + sd = hashmap_get(s->devices, &dev); + if (!sd) + /* Weird, we got an fd for a session device which wasn't recorded in the session state + * file... */ + return log_warning_errno(SYNTHETIC_ERRNO(ENODEV), "Got fd for missing session device [%u:%u] in session %s", + major(dev), minor(dev), s->id); - if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) { - log_debug("Device fd doesn't point to the expected character device node"); - close_nointr(fd); - continue; - } + log_debug("Attaching fd to session device [%u:%u] for session %s", + major(dev), minor(dev), s->id); + + session_device_attach_fd(sd, fd, s->was_active); + return 0; +} + +static int manager_attach_fds(Manager *m) { + _cleanup_strv_free_ char **fdnames = NULL; + int n; + + /* Upon restart, PID1 will send us back all fds of session devices that we previously opened. Each + * file descriptor is associated with a given session. The session ids are passed through FDNAMES. */ - sd = hashmap_get(s->devices, &dev); - if (!sd) { - /* Weird, we got an fd for a session device which wasn't - * recorded in the session state file... */ - log_warning("Got fd for missing session device [%u:%u] in session %s", - major(dev), minor(dev), s->id); - close_nointr(fd); + n = sd_listen_fds_with_names(true, &fdnames); + if (n < 0) + return log_warning_errno(n, "Failed to acquire passed fd list: %m"); + if (n == 0) + return 0; + + for (int i = 0; i < n; i++) { + int fd = SD_LISTEN_FDS_START + i; + + if (deliver_fd(m, fdnames[i], fd) >= 0) continue; - } - log_debug("Attaching fd to session device [%u:%u] for session %s", - major(dev), minor(dev), s->id); + /* Hmm, we couldn't deliver the fd to any session device object? If so, let's close the fd */ + safe_close(fd); - session_device_attach_fd(sd, fd, s->was_active); + /* Remove from fdstore as well */ + (void) sd_notifyf(false, + "FDSTOREREMOVE=1\n" + "FDNAME=%s", fdnames[i]); } return 0; @@ -492,11 +494,9 @@ static int manager_enumerate_sessions(Manager *m) { r = k; } - /* We might be restarted and PID1 could have sent us back the - * session device fds we previously saved. */ - k = manager_attach_fds(m); - if (k < 0) - log_warning_errno(k, "Failed to reattach session device fds: %m"); + /* We might be restarted and PID1 could have sent us back the session device fds we previously + * saved. */ + (void) manager_attach_fds(m); return r; } |