[Bug 1750013] Re: systemd-logind: memory leaks on session's connections (trusty-only)

Guilherme G. Piccoli 1750013 at bugs.launchpad.net
Fri Feb 16 18:41:34 UTC 2018


As already briefly mentioned, Trusty systemd's package has
additional patches to customize systemd - specially, we have the addition
of glue code to make Trusty's systemd work with cgmanager. This is
necessary due to the choice of upstart as init manager - it prevents
regular cgroup handling from systemd perspective, so cgmanager is used
in order to assist cgroup management on systemd code.

This glue code was used in some cgroup's routines when cgmanager is active
and running. In particular, it's used on systemd's cg_enumerate_tasks()
and cg_enumerate_processes() routines. In these cases, there's a memory
leak caused by a "string" allocation in cgm_get() that isn't freed on
cg_enumerate_tasks() / cg_enumerate_processes() - it shows up in Valgrind
like this:

58 bytes in 58 blocks are definitely lost in loss record 60 of 113
at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x638EB49: strdup (strdup.c:42)
by 0x422A90: cgm_get (cgmanager.c:148)
by 0x420AC6: cg_enumerate_tasks (cgroup-util.c:128)
by 0x420C89: cg_is_empty (cgroup-util.c:1129)
by 0x420DEA: cg_is_empty_recursive (cgroup-util.c:1175)
by 0x40FC48: session_check_gc (logind-session.c:979)
by 0x408694: manager_gc (logind.c:1503)
by 0x4094B8: manager_run (logind.c:1740)
by 0x40622B: main (logind.c:1868)
--

I wrote a small patch that fixes the leak by freeing the allocated pointer
after its use. It diverges from upstream since systemd upstream has no
cgmanager glue code, which was added specially for Trusty's need of
systemd packages without having it as init manager.

The free() calls are clear and simple, they're provided by a GCC attribute
that calls a free() whenever the scope of the pointer is not reachable
anymore. No side effects are expected, the patch frees the pointer in all
failure paths also since it's using the GCC attribute of auto-calling
free(). No double-frees are possible since the free() calls happens only
after the pointer was validated as has been successfully allocated.

The patch:

diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 6c07a49..ab50ad4 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -44,7 +44,7 @@ int cg_enumerate_processes(const char *controller, const char *path, FILE **_f)
         _cleanup_free_ char *fs = NULL;
         FILE *f;
         int r;
-        char *value = NULL;
+        _cleanup_free_ char *value = NULL;
         char *template = NULL;
         int fd;
 
@@ -111,7 +111,7 @@ int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
         _cleanup_free_ char *fs = NULL;
         FILE *f;
         int r;
-        char *value = NULL;
+        _cleanup_free_ char *value = NULL;
         char *template = NULL;
         int fd;
 

The patches above were tested during 4 days running the test-case, with
cgmanager package installed. More than 658000 sessions were started and
finished without memory leaks.

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to systemd in Ubuntu.
https://bugs.launchpad.net/bugs/1750013

Title:
  systemd-logind: memory leaks on session's connections (trusty-only)

Status in systemd package in Ubuntu:
  New

Bug description:
  It was observed that systemd-logind tool is leaking memory at each session
  connected. The issue happens in systemd from Trusty (14.04), which latest
  version currently (Feb/2018) is 204-5ubuntu20.26 (and still reproduces
  the bug).

  The basic test-case is to run the following loop from a remote
  machine:

  while true; do ssh <hostname-target> "whoami"; done

  and watch the increase in memory consumption from "systemd-logind" process
  in the target machine. One can use the "ps uax" command to verify the
  RSS of the process, or count the anon pages from /proc/<logind_pid>/smaps.

  To clarify a bit how a session works, the following "stack trace" details
  a bit which function calls happen when a SSH connection is opened, from
  Trusty's systemd-logind point of view:

  
  main() <logind.c>
  manager_startup()
  manager_run() [event-loop]
  bus_loop_dispatch() <dbus-loop.c>
  dbus_watch_handle() -> bus_manager_message_handler()
  bus_manager_create_session()
  manager_add_session() <logind.c>
  session_new() <logind-session.c>
  session_create_fifo()
  session_start()
  session_create_cgroup()
  session_save()
  session_bus_path()
  [...]

  After each session is closed, it was observed that session_free() isn't
  called, keeping the sessions alive. This can be verified through the
  command "loginctl list-session" - each session that once connected is
  present there "forever".

  The memory leaks can eventually lead to OOM situation of this process.
  Debug progress will be tracked here, in this LP.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1750013/+subscriptions



More information about the foundations-bugs mailing list