diff -Nru menu-cache-1.0.1/debian/changelog menu-cache-1.0.1/debian/changelog --- menu-cache-1.0.1/debian/changelog 2017-08-11 17:23:56.000000000 +0000 +++ menu-cache-1.0.1/debian/changelog 2018-01-29 05:15:59.000000000 +0000 @@ -1,3 +1,11 @@ +menu-cache (1.0.1-1ubuntu0.2) xenial; urgency=high + + * Fix menu-cached so 100% CPU isn't used after suspend (LP: #1635438). + - 90-1-fix-100-cpu-load.patch + - 90-2-fix-100-cpu-load.patch + + -- Simon Quigley Sun, 28 Jan 2018 23:15:59 -0600 + menu-cache (1.0.1-1ubuntu0.1) xenial-security; urgency=medium * SECURITY UPDATE: Socket may be blocked by another user (LP: #1703564) diff -Nru menu-cache-1.0.1/debian/patches/90-1-fix-100-cpu-load.patch menu-cache-1.0.1/debian/patches/90-1-fix-100-cpu-load.patch --- menu-cache-1.0.1/debian/patches/90-1-fix-100-cpu-load.patch 1970-01-01 00:00:00.000000000 +0000 +++ menu-cache-1.0.1/debian/patches/90-1-fix-100-cpu-load.patch 2018-01-29 05:15:59.000000000 +0000 @@ -0,0 +1,101 @@ +Description: Use freopen() instead of dup2() in menu-cached. + . + If dup2 called for fd 0 which is a socket instead of stdin, it will cause + a fail on accept() later. + . + Also terminate menu-cached in case of listening socket error. +Author: Andriy Grytsenko +Origin: upstream +Bug: https://github.com/lxde/menu-cache/issues/7 +Bug-Ubuntu: https://pad.lv/1635438 +Applied-Upstream: commit:fd52af607c +Last-Update: 2017-10-18 +--- a/NEWS ++++ b/NEWS +@@ -22,6 +22,8 @@ Changes in 1.0.1 since 1.0.0: + * Fixed potential access violation, use runtime user dir instead of tmp dir. + It limits libmenu-cache compatibility to menu-cached >= 0.7.0. + ++* Fixed 100% CPU load by menu-cached due to invalid dup2() call. ++ + + Changes in 1.0.0 since 0.7.0: + +--- a/menu-cache-daemon/menu-cached.c ++++ b/menu-cache-daemon/menu-cached.c +@@ -685,6 +685,14 @@ retry: + return ret; + } + ++static void terminate(int sig) ++{ ++/* #ifndef HAVE_ABSTRACT_SOCKETS */ ++ unlink(socket_file); ++ exit(0); ++/* #endif */ ++} ++ + static gboolean on_new_conn_incoming(GIOChannel* ch, GIOCondition cond, gpointer user_data) + { + int server, client; +@@ -699,7 +707,12 @@ static gboolean on_new_conn_incoming(GIO + if( client == -1 ) + { + DEBUG("accept error"); +- return TRUE; ++ if (errno == ECONNABORTED) ++ /* client failed, just continue */ ++ return TRUE; ++ /* else it's socket error, terminate server */ ++ terminate(SIGTERM); ++ return FALSE; + } + + child = g_io_channel_unix_new(client); +@@ -712,14 +725,6 @@ static gboolean on_new_conn_incoming(GIO + return TRUE; + } + +-static void terminate(int sig) +-{ +-/* #ifndef HAVE_ABSTRACT_SOCKETS */ +- unlink(socket_file); +- exit(0); +-/* #endif */ +-} +- + static gboolean on_server_conn_close(GIOChannel* ch, GIOCondition cond, gpointer user_data) + { + /* FIXME: is this possible? */ +@@ -734,7 +739,7 @@ int main(int argc, char** argv) + int server_fd; + struct sockaddr_un addr; + #ifndef DISABLE_DAEMONIZE +- int fd, pid; ++ pid_t pid; + + long open_max; + long i; +@@ -787,19 +792,9 @@ int main(int argc, char** argv) + } + + /* /dev/null for stdin, stdout, stderr */ +- fd = open ("/dev/null", O_RDONLY); +- if (fd != -1) +- { +- dup2 (fd, 0); +- close (fd); +- } +- fd = open ("/dev/null", O_WRONLY); +- if (fd != -1) +- { +- dup2 (fd, 1); +- dup2 (fd, 2); +- close (fd); +- } ++ if (freopen("/dev/null", "r", stdin)) i = i; ++ if (freopen("/dev/null", "w", stdout)) i = i; ++ if (freopen("/dev/null", "w", stderr)) i = i; + #endif + + signal(SIGHUP, terminate); diff -Nru menu-cache-1.0.1/debian/patches/90-2-fix-100-cpu-load.patch menu-cache-1.0.1/debian/patches/90-2-fix-100-cpu-load.patch --- menu-cache-1.0.1/debian/patches/90-2-fix-100-cpu-load.patch 1970-01-01 00:00:00.000000000 +0000 +++ menu-cache-1.0.1/debian/patches/90-2-fix-100-cpu-load.patch 2018-01-29 05:15:59.000000000 +0000 @@ -0,0 +1,118 @@ +Description: Open listening socket in the child, after closing all file descriptors. + . + Otherwise we step into closing it by freopen() in case if stdin was closed before. + This should finally fix the issue with accept() failure introduced by commit + c8794da0cf5a194b5eaadf020f02a5cab89f54fc very early which did dup2() on stdin + without any check if it's not assigned to the listening socket. +Author: Andriy Grytsenko +Origin: upstream +Bug: https://github.com/lxde/menu-cache/issues/7 +Bug-Ubuntu: https://pad.lv/1635438 +Applied-Upstream: 0335cce074, 8c8534159d +Last-Update: 2017-10-18 +--- a/menu-cache-daemon/menu-cached.c ++++ b/menu-cache-daemon/menu-cached.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #ifdef G_ENABLE_DEBUG + #define DEBUG(...) g_debug(__VA_ARGS__) +@@ -740,38 +741,25 @@ int main(int argc, char** argv) + struct sockaddr_un addr; + #ifndef DISABLE_DAEMONIZE + pid_t pid; ++ int status; + + long open_max; + long i; + #endif + +- memset(&addr, 0, sizeof(addr)); +- addr.sun_family = AF_UNIX; +- if (argc < 2) +- /* old way, not recommended! */ +- get_socket_name( addr.sun_path, sizeof( addr.sun_path ) ); +- else if (strlen(argv[1]) >= sizeof(addr.sun_path)) +- /* ouch, it's too big! */ +- return 1; +- else +- /* this is a good way! */ +- strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path) - 1); +- +- socket_file = addr.sun_path; +- +- server_fd = create_socket(&addr); +- +- if( server_fd < 0 ) +- return 1; +- + #ifndef DISABLE_DAEMONIZE + /* Become a daemon */ + if ((pid = fork()) < 0) { + g_error("can't fork"); ++ return 2; + } + else if (pid != 0) { ++ /* wait for result of child */ ++ while ((i = waitpid(pid, &status, 0)) < 0 && errno == EINTR); ++ if (i < 0 || !WIFEXITED(status)) /* system error or child crashed */ ++ return 127; + /* exit parent */ +- exit(0); ++ return WEXITSTATUS(status); + } + + /* reset session to forget about parent process completely */ +@@ -787,8 +775,7 @@ int main(int argc, char** argv) + for (i = 0; i < open_max; i++) + { + /* don't hold open fd opened besides server socket */ +- if (i != server_fd) +- fcntl (i, F_SETFD, FD_CLOEXEC); ++ fcntl (i, F_SETFD, FD_CLOEXEC); + } + + /* /dev/null for stdin, stdout, stderr */ +@@ -797,6 +784,39 @@ int main(int argc, char** argv) + if (freopen("/dev/null", "w", stderr)) i = i; + #endif + ++ memset(&addr, 0, sizeof(addr)); ++ addr.sun_family = AF_UNIX; ++ if (argc < 2) ++ /* old way, not recommended! */ ++ get_socket_name( addr.sun_path, sizeof( addr.sun_path ) ); ++ else if (strlen(argv[1]) >= sizeof(addr.sun_path)) ++ /* ouch, it's too big! */ ++ return 1; ++ else ++ /* this is a good way! */ ++ strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path) - 1); ++ ++ socket_file = addr.sun_path; ++ ++ server_fd = create_socket(&addr); ++ ++ if( server_fd < 0 ) ++ return 1; ++ ++#ifndef DISABLE_DAEMONIZE ++ /* Second fork to let parent get a result */ ++ if ((pid = fork()) < 0) { ++ g_error("can't fork"); ++ close(server_fd); ++ unlink(socket_file); ++ return 2; ++ } else if (pid != 0) { ++ /* exit child */ ++ return 0; ++ } ++ /* We are in grandchild now, daemonized */ ++#endif ++ + signal(SIGHUP, terminate); + signal(SIGINT, terminate); + signal(SIGQUIT, terminate); diff -Nru menu-cache-1.0.1/debian/patches/series menu-cache-1.0.1/debian/patches/series --- menu-cache-1.0.1/debian/patches/series 2017-08-11 17:23:56.000000000 +0000 +++ menu-cache-1.0.1/debian/patches/series 2018-01-29 05:15:45.000000000 +0000 @@ -1 +1,3 @@ fix-CVE-2017-8933.patch +90-1-fix-100-cpu-load.patch +90-2-fix-100-cpu-load.patch