diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-04-02 14:27:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-02 14:27:27 +0200 |
commit | 84ce204a93841776f022712d11219c616e585192 (patch) | |
tree | ca2a4af543e2b8e5f431b85fc2842aa3fff61794 | |
parent | 8a306989b3343e27edd7f59633b2d909781e0474 (diff) | |
parent | efc19ee4856f4dd5c47df466f3cc7f8496dd3c1a (diff) | |
download | systemd-84ce204a93841776f022712d11219c616e585192.tar.gz |
Merge pull request #12185 from poettering/login-unstore-fd
logind: remove unused fds from fdstore
-rw-r--r-- | src/login/logind-session-device.c | 20 | ||||
-rw-r--r-- | src/login/logind.c | 122 |
2 files changed, 66 insertions, 76 deletions
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index f358524ebc..7c79a4afdc 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -387,21 +387,11 @@ void session_device_free(SessionDevice *sd) { assert(sd); /* Make sure to remove the pushed fd. */ - if (sd->pushed_fd) { - _cleanup_free_ char *m = NULL; - const char *id; - int r; - - /* Session ID does not contain separators. */ - id = sd->session->id; - assert(*(id + strcspn(id, "-\n")) == '\0'); - - r = asprintf(&m, "FDSTOREREMOVE=1\n" - "FDNAME=session-%s-device-%u-%u\n", - id, major(sd->dev), minor(sd->dev)); - if (r >= 0) - (void) sd_notify(false, m); - } + if (sd->pushed_fd) + (void) sd_notifyf(false, + "FDSTOREREMOVE=1\n" + "FDNAME=session-%s-device-%u-%u", + sd->session->id, major(sd->dev), minor(sd->dev)); session_device_stop(sd); session_device_notify(sd, SESSION_DEVICE_RELEASE); 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; } |