1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-19 18:13:55 +00:00

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.
This commit is contained in:
Andreas Schwab 2012-03-11 12:15:25 +01:00
parent 300e8fa562
commit 6b0c89847a
2 changed files with 58 additions and 67 deletions

View File

@ -1,3 +1,16 @@
2012-03-11 Andreas Schwab <schwab@linux-m68k.org>
* 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 <rgm@gnu.org>
* ebrowse.c (version) <emacs_copyright>:

View File

@ -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);
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 (socket_name) < sizeof (server.sun_path))
strcpy (server.sun_path, socket_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 ();
}