From 6b0c89847a6291b41f73658a4a9c5d54761b2ab9 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sun, 11 Mar 2012 12:15:25 +0100 Subject: [PATCH] Don't access freed memory in emacsclient * emacsclient.c (socket_name): Add const. (get_server_config): Add parameter config_file, use it instead of global server_file. (set_tcp_socket): Add parameter local_server_file, pass it down to get_server_config. (set_local_socket): Add parameter local_socket_name, use it instead of global socket_name. (set_socket): Adjust calls to set_local_socket and set_tcp_socket. Don't clobber global server_file or socket_name. (main): No longer reset server_file or socket_name. --- lib-src/ChangeLog | 13 +++++ lib-src/emacsclient.c | 114 +++++++++++++++++------------------------- 2 files changed, 59 insertions(+), 68 deletions(-) diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 32054e68db2..b349533f87f 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,16 @@ +2012-03-11 Andreas Schwab + + * emacsclient.c (socket_name): Add const. + (get_server_config): Add parameter config_file, use it instead of + global server_file. + (set_tcp_socket): Add parameter local_server_file, pass it down to + get_server_config. + (set_local_socket): Add parameter local_socket_name, use it + instead of global socket_name. + (set_socket): Adjust calls to set_local_socket and set_tcp_socket. + Don't clobber global server_file or socket_name. + (main): No longer reset server_file or socket_name. + 2012-01-05 Glenn Morris * ebrowse.c (version) : diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 11eba2792d6..8779309f9b3 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -152,7 +152,7 @@ int tty = 0; const char *alternate_editor = NULL; /* If non-NULL, the filename of the UNIX socket. */ -char *socket_name = NULL; +const char *socket_name = NULL; /* If non-NULL, the filename of the authentication file. */ const char *server_file = NULL; @@ -955,36 +955,37 @@ initialize_sockets (void) * the Emacs server: host, port, and authentication string. */ static int -get_server_config (struct sockaddr_in *server, char *authentication) +get_server_config (const char *config_file, struct sockaddr_in *server, + char *authentication) { char dotted[32]; char *port; FILE *config = NULL; - if (file_name_absolute_p (server_file)) - config = fopen (server_file, "rb"); + if (file_name_absolute_p (config_file)) + config = fopen (config_file, "rb"); else { const char *home = egetenv ("HOME"); if (home) { - char *path = xmalloc (strlen (home) + strlen (server_file) + char *path = xmalloc (strlen (home) + strlen (config_file) + EXTRA_SPACE); strcpy (path, home); strcat (path, "/.emacs.d/server/"); - strcat (path, server_file); + strcat (path, config_file); config = fopen (path, "rb"); free (path); } #ifdef WINDOWSNT if (!config && (home = egetenv ("APPDATA"))) { - char *path = xmalloc (strlen (home) + strlen (server_file) + char *path = xmalloc (strlen (home) + strlen (config_file) + EXTRA_SPACE); strcpy (path, home); strcat (path, "/.emacs.d/server/"); - strcat (path, server_file); + strcat (path, config_file); config = fopen (path, "rb"); free (path); } @@ -1019,14 +1020,14 @@ get_server_config (struct sockaddr_in *server, char *authentication) } static HSOCKET -set_tcp_socket (void) +set_tcp_socket (const char *local_server_file) { HSOCKET s; struct sockaddr_in server; struct linger l_arg = {1, 1}; char auth_string[AUTH_KEY_LENGTH + 1]; - if (! get_server_config (&server, auth_string)) + if (! get_server_config (local_server_file, &server, auth_string)) return INVALID_SOCKET; if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) @@ -1236,7 +1237,7 @@ init_signals (void) static HSOCKET -set_local_socket (void) +set_local_socket (const char *local_socket_name) { HSOCKET s; struct sockaddr_un server; @@ -1254,27 +1255,20 @@ set_local_socket (void) server.sun_family = AF_UNIX; { - int sock_status = 0; - int default_sock = !socket_name; - int saved_errno = 0; - const char *server_name = "server"; + int sock_status; + int use_tmpdir = 0; + int saved_errno; + const char *server_name = local_socket_name; const char *tmpdir IF_LINT ( = NULL); char *tmpdir_storage = NULL; char *socket_name_storage = NULL; - if (socket_name && !strchr (socket_name, '/') - && !strchr (socket_name, '\\')) + if (!strchr (local_socket_name, '/') && !strchr (local_socket_name, '\\')) { /* socket_name is a file name component. */ - server_name = socket_name; - socket_name = NULL; - default_sock = 1; /* Try both UIDs. */ - } - - if (default_sock) - { long uid = geteuid (); ptrdiff_t tmpdirlen; + use_tmpdir = 1; tmpdir = egetenv ("TMPDIR"); if (!tmpdir) { @@ -1293,26 +1287,27 @@ set_local_socket (void) tmpdir = "/tmp"; } tmpdirlen = strlen (tmpdir); - socket_name = socket_name_storage = + socket_name_storage = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); - strcpy (socket_name, tmpdir); - sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); - strcat (socket_name + tmpdirlen, server_name); + strcpy (socket_name_storage, tmpdir); + sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid); + strcat (socket_name_storage + tmpdirlen, server_name); + local_socket_name = socket_name_storage; } - if (strlen (socket_name) < sizeof (server.sun_path)) - strcpy (server.sun_path, socket_name); + if (strlen (local_socket_name) < sizeof (server.sun_path)) + strcpy (server.sun_path, local_socket_name); else { message (TRUE, "%s: socket-name %s too long\n", - progname, socket_name); + progname, local_socket_name); fail (); } /* See if the socket exists, and if it's owned by us. */ sock_status = socket_status (server.sun_path); saved_errno = errno; - if (sock_status && default_sock) + if (sock_status && use_tmpdir) { /* Failing that, see if LOGNAME or USER exist and differ from our euid. If so, look for a socket based on the UID @@ -1333,21 +1328,21 @@ set_local_socket (void) /* We're running under su, apparently. */ long uid = pw->pw_uid; ptrdiff_t tmpdirlen = strlen (tmpdir); - socket_name = xmalloc (tmpdirlen + strlen (server_name) - + EXTRA_SPACE); - strcpy (socket_name, tmpdir); - sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); - strcat (socket_name + tmpdirlen, server_name); - - if (strlen (socket_name) < sizeof (server.sun_path)) - strcpy (server.sun_path, socket_name); + char *user_socket_name + = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); + strcpy (user_socket_name, tmpdir); + sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid); + strcat (user_socket_name + tmpdirlen, server_name); + + if (strlen (user_socket_name) < sizeof (server.sun_path)) + strcpy (server.sun_path, user_socket_name); else { message (TRUE, "%s: socket-name %s too long\n", - progname, socket_name); + progname, user_socket_name); exit (EXIT_FAILURE); } - free (socket_name); + free (user_socket_name); sock_status = socket_status (server.sun_path); saved_errno = errno; @@ -1401,6 +1396,7 @@ static HSOCKET set_socket (int no_exit_if_error) { HSOCKET s; + const char *local_server_file = server_file; INITIALIZE (); @@ -1408,7 +1404,7 @@ set_socket (int no_exit_if_error) /* Explicit --socket-name argument. */ if (socket_name) { - s = set_local_socket (); + s = set_local_socket (socket_name); if ((s != INVALID_SOCKET) || no_exit_if_error) return s; message (TRUE, "%s: error accessing socket \"%s\"\n", @@ -1418,30 +1414,29 @@ set_socket (int no_exit_if_error) #endif /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */ - if (!server_file) - server_file = egetenv ("EMACS_SERVER_FILE"); + if (!local_server_file) + local_server_file = egetenv ("EMACS_SERVER_FILE"); - if (server_file) + if (local_server_file) { - s = set_tcp_socket (); + s = set_tcp_socket (local_server_file); if ((s != INVALID_SOCKET) || no_exit_if_error) return s; message (TRUE, "%s: error accessing server file \"%s\"\n", - progname, server_file); + progname, local_server_file); exit (EXIT_FAILURE); } #ifndef NO_SOCKETS_IN_FILE_SYSTEM /* Implicit local socket. */ - s = set_local_socket (); + s = set_local_socket ("server"); if (s != INVALID_SOCKET) return s; #endif /* Implicit server file. */ - server_file = "server"; - s = set_tcp_socket (); + s = set_tcp_socket ("server"); if ((s != INVALID_SOCKET) || no_exit_if_error) return s; @@ -1573,8 +1568,6 @@ main (int argc, char **argv) int rl = 0, needlf = 0; char *cwd, *str; char string[BUFSIZ+1]; - int null_socket_name IF_LINT ( = 0); - int null_server_file IF_LINT ( = 0); int start_daemon_if_needed; int exit_status = EXIT_SUCCESS; @@ -1602,14 +1595,6 @@ main (int argc, char **argv) in case of failure to connect. */ start_daemon_if_needed = (alternate_editor && (alternate_editor[0] == '\0')); - if (start_daemon_if_needed) - { - /* set_socket changes the values for socket_name and - server_file, we need to reset them, if they were NULL before - for the second call to set_socket. */ - null_socket_name = (socket_name == NULL); - null_server_file = (server_file == NULL); - } emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); if (emacs_socket == INVALID_SOCKET) @@ -1617,13 +1602,6 @@ main (int argc, char **argv) if (! start_daemon_if_needed) fail (); - /* Reset socket_name and server_file if they were NULL - before the set_socket call. */ - if (null_socket_name) - socket_name = NULL; - if (null_server_file) - server_file = NULL; - start_daemon_and_retry_set_socket (); } -- 2.39.2