diff options
| author | Andreas Schwab | 2012-03-11 12:15:25 +0100 |
|---|---|---|
| committer | Andreas Schwab | 2012-03-11 12:15:25 +0100 |
| commit | 6b0c89847a6291b41f73658a4a9c5d54761b2ab9 (patch) | |
| tree | f9b92f60981a8ae940031eb5dd1b228f87393bf5 | |
| parent | 300e8fa5624c0670553c1215409c9d31075901d1 (diff) | |
| download | emacs-6b0c89847a6291b41f73658a4a9c5d54761b2ab9.tar.gz emacs-6b0c89847a6291b41f73658a4a9c5d54761b2ab9.zip | |
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.
| -rw-r--r-- | lib-src/ChangeLog | 13 | ||||
| -rw-r--r-- | 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 @@ | |||
| 1 | 2012-03-11 Andreas Schwab <schwab@linux-m68k.org> | ||
| 2 | |||
| 3 | * emacsclient.c (socket_name): Add const. | ||
| 4 | (get_server_config): Add parameter config_file, use it instead of | ||
| 5 | global server_file. | ||
| 6 | (set_tcp_socket): Add parameter local_server_file, pass it down to | ||
| 7 | get_server_config. | ||
| 8 | (set_local_socket): Add parameter local_socket_name, use it | ||
| 9 | instead of global socket_name. | ||
| 10 | (set_socket): Adjust calls to set_local_socket and set_tcp_socket. | ||
| 11 | Don't clobber global server_file or socket_name. | ||
| 12 | (main): No longer reset server_file or socket_name. | ||
| 13 | |||
| 1 | 2012-01-05 Glenn Morris <rgm@gnu.org> | 14 | 2012-01-05 Glenn Morris <rgm@gnu.org> |
| 2 | 15 | ||
| 3 | * ebrowse.c (version) <emacs_copyright>: | 16 | * ebrowse.c (version) <emacs_copyright>: |
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; | |||
| 152 | const char *alternate_editor = NULL; | 152 | const char *alternate_editor = NULL; |
| 153 | 153 | ||
| 154 | /* If non-NULL, the filename of the UNIX socket. */ | 154 | /* If non-NULL, the filename of the UNIX socket. */ |
| 155 | char *socket_name = NULL; | 155 | const char *socket_name = NULL; |
| 156 | 156 | ||
| 157 | /* If non-NULL, the filename of the authentication file. */ | 157 | /* If non-NULL, the filename of the authentication file. */ |
| 158 | const char *server_file = NULL; | 158 | const char *server_file = NULL; |
| @@ -955,36 +955,37 @@ initialize_sockets (void) | |||
| 955 | * the Emacs server: host, port, and authentication string. | 955 | * the Emacs server: host, port, and authentication string. |
| 956 | */ | 956 | */ |
| 957 | static int | 957 | static int |
| 958 | get_server_config (struct sockaddr_in *server, char *authentication) | 958 | get_server_config (const char *config_file, struct sockaddr_in *server, |
| 959 | char *authentication) | ||
| 959 | { | 960 | { |
| 960 | char dotted[32]; | 961 | char dotted[32]; |
| 961 | char *port; | 962 | char *port; |
| 962 | FILE *config = NULL; | 963 | FILE *config = NULL; |
| 963 | 964 | ||
| 964 | if (file_name_absolute_p (server_file)) | 965 | if (file_name_absolute_p (config_file)) |
| 965 | config = fopen (server_file, "rb"); | 966 | config = fopen (config_file, "rb"); |
| 966 | else | 967 | else |
| 967 | { | 968 | { |
| 968 | const char *home = egetenv ("HOME"); | 969 | const char *home = egetenv ("HOME"); |
| 969 | 970 | ||
| 970 | if (home) | 971 | if (home) |
| 971 | { | 972 | { |
| 972 | char *path = xmalloc (strlen (home) + strlen (server_file) | 973 | char *path = xmalloc (strlen (home) + strlen (config_file) |
| 973 | + EXTRA_SPACE); | 974 | + EXTRA_SPACE); |
| 974 | strcpy (path, home); | 975 | strcpy (path, home); |
| 975 | strcat (path, "/.emacs.d/server/"); | 976 | strcat (path, "/.emacs.d/server/"); |
| 976 | strcat (path, server_file); | 977 | strcat (path, config_file); |
| 977 | config = fopen (path, "rb"); | 978 | config = fopen (path, "rb"); |
| 978 | free (path); | 979 | free (path); |
| 979 | } | 980 | } |
| 980 | #ifdef WINDOWSNT | 981 | #ifdef WINDOWSNT |
| 981 | if (!config && (home = egetenv ("APPDATA"))) | 982 | if (!config && (home = egetenv ("APPDATA"))) |
| 982 | { | 983 | { |
| 983 | char *path = xmalloc (strlen (home) + strlen (server_file) | 984 | char *path = xmalloc (strlen (home) + strlen (config_file) |
| 984 | + EXTRA_SPACE); | 985 | + EXTRA_SPACE); |
| 985 | strcpy (path, home); | 986 | strcpy (path, home); |
| 986 | strcat (path, "/.emacs.d/server/"); | 987 | strcat (path, "/.emacs.d/server/"); |
| 987 | strcat (path, server_file); | 988 | strcat (path, config_file); |
| 988 | config = fopen (path, "rb"); | 989 | config = fopen (path, "rb"); |
| 989 | free (path); | 990 | free (path); |
| 990 | } | 991 | } |
| @@ -1019,14 +1020,14 @@ get_server_config (struct sockaddr_in *server, char *authentication) | |||
| 1019 | } | 1020 | } |
| 1020 | 1021 | ||
| 1021 | static HSOCKET | 1022 | static HSOCKET |
| 1022 | set_tcp_socket (void) | 1023 | set_tcp_socket (const char *local_server_file) |
| 1023 | { | 1024 | { |
| 1024 | HSOCKET s; | 1025 | HSOCKET s; |
| 1025 | struct sockaddr_in server; | 1026 | struct sockaddr_in server; |
| 1026 | struct linger l_arg = {1, 1}; | 1027 | struct linger l_arg = {1, 1}; |
| 1027 | char auth_string[AUTH_KEY_LENGTH + 1]; | 1028 | char auth_string[AUTH_KEY_LENGTH + 1]; |
| 1028 | 1029 | ||
| 1029 | if (! get_server_config (&server, auth_string)) | 1030 | if (! get_server_config (local_server_file, &server, auth_string)) |
| 1030 | return INVALID_SOCKET; | 1031 | return INVALID_SOCKET; |
| 1031 | 1032 | ||
| 1032 | if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) | 1033 | if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) |
| @@ -1236,7 +1237,7 @@ init_signals (void) | |||
| 1236 | 1237 | ||
| 1237 | 1238 | ||
| 1238 | static HSOCKET | 1239 | static HSOCKET |
| 1239 | set_local_socket (void) | 1240 | set_local_socket (const char *local_socket_name) |
| 1240 | { | 1241 | { |
| 1241 | HSOCKET s; | 1242 | HSOCKET s; |
| 1242 | struct sockaddr_un server; | 1243 | struct sockaddr_un server; |
| @@ -1254,27 +1255,20 @@ set_local_socket (void) | |||
| 1254 | server.sun_family = AF_UNIX; | 1255 | server.sun_family = AF_UNIX; |
| 1255 | 1256 | ||
| 1256 | { | 1257 | { |
| 1257 | int sock_status = 0; | 1258 | int sock_status; |
| 1258 | int default_sock = !socket_name; | 1259 | int use_tmpdir = 0; |
| 1259 | int saved_errno = 0; | 1260 | int saved_errno; |
| 1260 | const char *server_name = "server"; | 1261 | const char *server_name = local_socket_name; |
| 1261 | const char *tmpdir IF_LINT ( = NULL); | 1262 | const char *tmpdir IF_LINT ( = NULL); |
| 1262 | char *tmpdir_storage = NULL; | 1263 | char *tmpdir_storage = NULL; |
| 1263 | char *socket_name_storage = NULL; | 1264 | char *socket_name_storage = NULL; |
| 1264 | 1265 | ||
| 1265 | if (socket_name && !strchr (socket_name, '/') | 1266 | if (!strchr (local_socket_name, '/') && !strchr (local_socket_name, '\\')) |
| 1266 | && !strchr (socket_name, '\\')) | ||
| 1267 | { | 1267 | { |
| 1268 | /* socket_name is a file name component. */ | 1268 | /* socket_name is a file name component. */ |
| 1269 | server_name = socket_name; | ||
| 1270 | socket_name = NULL; | ||
| 1271 | default_sock = 1; /* Try both UIDs. */ | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | if (default_sock) | ||
| 1275 | { | ||
| 1276 | long uid = geteuid (); | 1269 | long uid = geteuid (); |
| 1277 | ptrdiff_t tmpdirlen; | 1270 | ptrdiff_t tmpdirlen; |
| 1271 | use_tmpdir = 1; | ||
| 1278 | tmpdir = egetenv ("TMPDIR"); | 1272 | tmpdir = egetenv ("TMPDIR"); |
| 1279 | if (!tmpdir) | 1273 | if (!tmpdir) |
| 1280 | { | 1274 | { |
| @@ -1293,26 +1287,27 @@ set_local_socket (void) | |||
| 1293 | tmpdir = "/tmp"; | 1287 | tmpdir = "/tmp"; |
| 1294 | } | 1288 | } |
| 1295 | tmpdirlen = strlen (tmpdir); | 1289 | tmpdirlen = strlen (tmpdir); |
| 1296 | socket_name = socket_name_storage = | 1290 | socket_name_storage = |
| 1297 | xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); | 1291 | xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); |
| 1298 | strcpy (socket_name, tmpdir); | 1292 | strcpy (socket_name_storage, tmpdir); |
| 1299 | sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); | 1293 | sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid); |
| 1300 | strcat (socket_name + tmpdirlen, server_name); | 1294 | strcat (socket_name_storage + tmpdirlen, server_name); |
| 1295 | local_socket_name = socket_name_storage; | ||
| 1301 | } | 1296 | } |
| 1302 | 1297 | ||
| 1303 | if (strlen (socket_name) < sizeof (server.sun_path)) | 1298 | if (strlen (local_socket_name) < sizeof (server.sun_path)) |
| 1304 | strcpy (server.sun_path, socket_name); | 1299 | strcpy (server.sun_path, local_socket_name); |
| 1305 | else | 1300 | else |
| 1306 | { | 1301 | { |
| 1307 | message (TRUE, "%s: socket-name %s too long\n", | 1302 | message (TRUE, "%s: socket-name %s too long\n", |
| 1308 | progname, socket_name); | 1303 | progname, local_socket_name); |
| 1309 | fail (); | 1304 | fail (); |
| 1310 | } | 1305 | } |
| 1311 | 1306 | ||
| 1312 | /* See if the socket exists, and if it's owned by us. */ | 1307 | /* See if the socket exists, and if it's owned by us. */ |
| 1313 | sock_status = socket_status (server.sun_path); | 1308 | sock_status = socket_status (server.sun_path); |
| 1314 | saved_errno = errno; | 1309 | saved_errno = errno; |
| 1315 | if (sock_status && default_sock) | 1310 | if (sock_status && use_tmpdir) |
| 1316 | { | 1311 | { |
| 1317 | /* Failing that, see if LOGNAME or USER exist and differ from | 1312 | /* Failing that, see if LOGNAME or USER exist and differ from |
| 1318 | our euid. If so, look for a socket based on the UID | 1313 | our euid. If so, look for a socket based on the UID |
| @@ -1333,21 +1328,21 @@ set_local_socket (void) | |||
| 1333 | /* We're running under su, apparently. */ | 1328 | /* We're running under su, apparently. */ |
| 1334 | long uid = pw->pw_uid; | 1329 | long uid = pw->pw_uid; |
| 1335 | ptrdiff_t tmpdirlen = strlen (tmpdir); | 1330 | ptrdiff_t tmpdirlen = strlen (tmpdir); |
| 1336 | socket_name = xmalloc (tmpdirlen + strlen (server_name) | 1331 | char *user_socket_name |
| 1337 | + EXTRA_SPACE); | 1332 | = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); |
| 1338 | strcpy (socket_name, tmpdir); | 1333 | strcpy (user_socket_name, tmpdir); |
| 1339 | sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid); | 1334 | sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid); |
| 1340 | strcat (socket_name + tmpdirlen, server_name); | 1335 | strcat (user_socket_name + tmpdirlen, server_name); |
| 1341 | 1336 | ||
| 1342 | if (strlen (socket_name) < sizeof (server.sun_path)) | 1337 | if (strlen (user_socket_name) < sizeof (server.sun_path)) |
| 1343 | strcpy (server.sun_path, socket_name); | 1338 | strcpy (server.sun_path, user_socket_name); |
| 1344 | else | 1339 | else |
| 1345 | { | 1340 | { |
| 1346 | message (TRUE, "%s: socket-name %s too long\n", | 1341 | message (TRUE, "%s: socket-name %s too long\n", |
| 1347 | progname, socket_name); | 1342 | progname, user_socket_name); |
| 1348 | exit (EXIT_FAILURE); | 1343 | exit (EXIT_FAILURE); |
| 1349 | } | 1344 | } |
| 1350 | free (socket_name); | 1345 | free (user_socket_name); |
| 1351 | 1346 | ||
| 1352 | sock_status = socket_status (server.sun_path); | 1347 | sock_status = socket_status (server.sun_path); |
| 1353 | saved_errno = errno; | 1348 | saved_errno = errno; |
| @@ -1401,6 +1396,7 @@ static HSOCKET | |||
| 1401 | set_socket (int no_exit_if_error) | 1396 | set_socket (int no_exit_if_error) |
| 1402 | { | 1397 | { |
| 1403 | HSOCKET s; | 1398 | HSOCKET s; |
| 1399 | const char *local_server_file = server_file; | ||
| 1404 | 1400 | ||
| 1405 | INITIALIZE (); | 1401 | INITIALIZE (); |
| 1406 | 1402 | ||
| @@ -1408,7 +1404,7 @@ set_socket (int no_exit_if_error) | |||
| 1408 | /* Explicit --socket-name argument. */ | 1404 | /* Explicit --socket-name argument. */ |
| 1409 | if (socket_name) | 1405 | if (socket_name) |
| 1410 | { | 1406 | { |
| 1411 | s = set_local_socket (); | 1407 | s = set_local_socket (socket_name); |
| 1412 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1408 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1413 | return s; | 1409 | return s; |
| 1414 | message (TRUE, "%s: error accessing socket \"%s\"\n", | 1410 | message (TRUE, "%s: error accessing socket \"%s\"\n", |
| @@ -1418,30 +1414,29 @@ set_socket (int no_exit_if_error) | |||
| 1418 | #endif | 1414 | #endif |
| 1419 | 1415 | ||
| 1420 | /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */ | 1416 | /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */ |
| 1421 | if (!server_file) | 1417 | if (!local_server_file) |
| 1422 | server_file = egetenv ("EMACS_SERVER_FILE"); | 1418 | local_server_file = egetenv ("EMACS_SERVER_FILE"); |
| 1423 | 1419 | ||
| 1424 | if (server_file) | 1420 | if (local_server_file) |
| 1425 | { | 1421 | { |
| 1426 | s = set_tcp_socket (); | 1422 | s = set_tcp_socket (local_server_file); |
| 1427 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1423 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1428 | return s; | 1424 | return s; |
| 1429 | 1425 | ||
| 1430 | message (TRUE, "%s: error accessing server file \"%s\"\n", | 1426 | message (TRUE, "%s: error accessing server file \"%s\"\n", |
| 1431 | progname, server_file); | 1427 | progname, local_server_file); |
| 1432 | exit (EXIT_FAILURE); | 1428 | exit (EXIT_FAILURE); |
| 1433 | } | 1429 | } |
| 1434 | 1430 | ||
| 1435 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | 1431 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 1436 | /* Implicit local socket. */ | 1432 | /* Implicit local socket. */ |
| 1437 | s = set_local_socket (); | 1433 | s = set_local_socket ("server"); |
| 1438 | if (s != INVALID_SOCKET) | 1434 | if (s != INVALID_SOCKET) |
| 1439 | return s; | 1435 | return s; |
| 1440 | #endif | 1436 | #endif |
| 1441 | 1437 | ||
| 1442 | /* Implicit server file. */ | 1438 | /* Implicit server file. */ |
| 1443 | server_file = "server"; | 1439 | s = set_tcp_socket ("server"); |
| 1444 | s = set_tcp_socket (); | ||
| 1445 | if ((s != INVALID_SOCKET) || no_exit_if_error) | 1440 | if ((s != INVALID_SOCKET) || no_exit_if_error) |
| 1446 | return s; | 1441 | return s; |
| 1447 | 1442 | ||
| @@ -1573,8 +1568,6 @@ main (int argc, char **argv) | |||
| 1573 | int rl = 0, needlf = 0; | 1568 | int rl = 0, needlf = 0; |
| 1574 | char *cwd, *str; | 1569 | char *cwd, *str; |
| 1575 | char string[BUFSIZ+1]; | 1570 | char string[BUFSIZ+1]; |
| 1576 | int null_socket_name IF_LINT ( = 0); | ||
| 1577 | int null_server_file IF_LINT ( = 0); | ||
| 1578 | int start_daemon_if_needed; | 1571 | int start_daemon_if_needed; |
| 1579 | int exit_status = EXIT_SUCCESS; | 1572 | int exit_status = EXIT_SUCCESS; |
| 1580 | 1573 | ||
| @@ -1602,14 +1595,6 @@ main (int argc, char **argv) | |||
| 1602 | in case of failure to connect. */ | 1595 | in case of failure to connect. */ |
| 1603 | start_daemon_if_needed = (alternate_editor | 1596 | start_daemon_if_needed = (alternate_editor |
| 1604 | && (alternate_editor[0] == '\0')); | 1597 | && (alternate_editor[0] == '\0')); |
| 1605 | if (start_daemon_if_needed) | ||
| 1606 | { | ||
| 1607 | /* set_socket changes the values for socket_name and | ||
| 1608 | server_file, we need to reset them, if they were NULL before | ||
| 1609 | for the second call to set_socket. */ | ||
| 1610 | null_socket_name = (socket_name == NULL); | ||
| 1611 | null_server_file = (server_file == NULL); | ||
| 1612 | } | ||
| 1613 | 1598 | ||
| 1614 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); | 1599 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); |
| 1615 | if (emacs_socket == INVALID_SOCKET) | 1600 | if (emacs_socket == INVALID_SOCKET) |
| @@ -1617,13 +1602,6 @@ main (int argc, char **argv) | |||
| 1617 | if (! start_daemon_if_needed) | 1602 | if (! start_daemon_if_needed) |
| 1618 | fail (); | 1603 | fail (); |
| 1619 | 1604 | ||
| 1620 | /* Reset socket_name and server_file if they were NULL | ||
| 1621 | before the set_socket call. */ | ||
| 1622 | if (null_socket_name) | ||
| 1623 | socket_name = NULL; | ||
| 1624 | if (null_server_file) | ||
| 1625 | server_file = NULL; | ||
| 1626 | |||
| 1627 | start_daemon_and_retry_set_socket (); | 1605 | start_daemon_and_retry_set_socket (); |
| 1628 | } | 1606 | } |
| 1629 | 1607 | ||