diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-11-29 11:55:37 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-11-29 11:55:37 +0000 |
commit | acb67a784fba86d2cc89556ce88fe30fd8d98b84 (patch) | |
tree | ad7cdae028c4cf586914c9ce69adc4f5a49ea5e6 | |
parent | 820bcbf5b76eaec67ea88970dd5d236b2b25b151 (diff) | |
download | libextractor-acb67a784fba86d2cc89556ce88fe30fd8d98b84.tar.gz libextractor-acb67a784fba86d2cc89556ce88fe30fd8d98b84.zip |
LRN:
1) Use PATH_SEPARATOR_STR instead of ":" to tokenize prefix
2) Correctly close cpipe_out and cpipe_in on W32
3) Use page-backed memory mapping instead of a file-backed one (give
the child process a name of the mapping instead of a file name).
4) Add RundllEntryPointA() (which calls RundllEntryPoint() anyway),
doesn't work on NT 6.1 without it.
5) Pass duplicated HANDLEs to the child, not CRT file IDs (apparently,
CRT file IDs are not inherited).
6) Call CreateProcess correctly (so that it finds rundll32 in PATH).
7) Write data into the child's input pipe AFTER the child starts
(otherwise there is a probability of making a blocking write and
hanging up).
AFAICS, passing the test requires LIBEXTRACTOR_PREFIX to be set and
pointing to $GNUNET_PREFIX/lib/libextractor directory
-rw-r--r-- | doc/version.texi | 4 | ||||
-rw-r--r-- | src/main/extractor.c | 200 |
2 files changed, 136 insertions, 68 deletions
diff --git a/doc/version.texi b/doc/version.texi index 63e8c09..a604aa2 100644 --- a/doc/version.texi +++ b/doc/version.texi | |||
@@ -1,4 +1,4 @@ | |||
1 | @set UPDATED 17 May 2010 | 1 | @set UPDATED 1 April 2010 |
2 | @set UPDATED-MONTH May 2010 | 2 | @set UPDATED-MONTH April 2010 |
3 | @set EDITION 0.6.3 | 3 | @set EDITION 0.6.3 |
4 | @set VERSION 0.6.3 | 4 | @set VERSION 0.6.3 |
diff --git a/src/main/extractor.c b/src/main/extractor.c index 4fb5b18..5208e3b 100644 --- a/src/main/extractor.c +++ b/src/main/extractor.c | |||
@@ -449,11 +449,11 @@ get_installation_paths (PathProcessor pp, | |||
449 | d = strdup (p); | 449 | d = strdup (p); |
450 | if (d == NULL) | 450 | if (d == NULL) |
451 | return; | 451 | return; |
452 | prefix = strtok (d, ":"); | 452 | prefix = strtok (d, PATH_SEPARATOR_STR); |
453 | while (NULL != prefix) | 453 | while (NULL != prefix) |
454 | { | 454 | { |
455 | pp (pp_cls, prefix); | 455 | pp (pp_cls, prefix); |
456 | prefix = strtok (NULL, ":"); | 456 | prefix = strtok (NULL, PATH_SEPARATOR_STR); |
457 | } | 457 | } |
458 | free (d); | 458 | free (d); |
459 | return; | 459 | return; |
@@ -982,8 +982,8 @@ stop_process (struct EXTRACTOR_PluginList *plugin) | |||
982 | TerminateProcess (plugin->hProcess, 0); | 982 | TerminateProcess (plugin->hProcess, 0); |
983 | CloseHandle (plugin->hProcess); | 983 | CloseHandle (plugin->hProcess); |
984 | plugin->hProcess = INVALID_HANDLE_VALUE; | 984 | plugin->hProcess = INVALID_HANDLE_VALUE; |
985 | CloseHandle (plugin->cpipe_out); | 985 | close (plugin->cpipe_out); |
986 | CloseHandle (plugin->cpipe_in); | 986 | fclose (plugin->cpipe_in); |
987 | #endif | 987 | #endif |
988 | plugin->cpipe_out = -1; | 988 | plugin->cpipe_out = -1; |
989 | plugin->cpipe_in = NULL; | 989 | plugin->cpipe_in = NULL; |
@@ -1186,6 +1186,7 @@ process_requests (struct EXTRACTOR_PluginList *plugin, | |||
1186 | int do_break; | 1186 | int do_break; |
1187 | #ifdef WINDOWS | 1187 | #ifdef WINDOWS |
1188 | HANDLE map; | 1188 | HANDLE map; |
1189 | MEMORY_BASIC_INFORMATION mi; | ||
1189 | #endif | 1190 | #endif |
1190 | 1191 | ||
1191 | if (plugin == NULL) | 1192 | if (plugin == NULL) |
@@ -1262,9 +1263,23 @@ process_requests (struct EXTRACTOR_PluginList *plugin, | |||
1262 | (NULL != (ptr = mmap (NULL, size, PROT_READ, MAP_SHARED, shmid, 0))) && | 1263 | (NULL != (ptr = mmap (NULL, size, PROT_READ, MAP_SHARED, shmid, 0))) && |
1263 | (ptr != (void*) -1) ) | 1264 | (ptr != (void*) -1) ) |
1264 | #else | 1265 | #else |
1265 | map = OpenFileMapping (PAGE_READONLY, FALSE, fn); | 1266 | /* Despite the obvious, this must be READWRITE, not READONLY */ |
1267 | map = OpenFileMapping (PAGE_READWRITE, FALSE, fn); | ||
1266 | ptr = MapViewOfFile (map, FILE_MAP_READ, 0, 0, 0); | 1268 | ptr = MapViewOfFile (map, FILE_MAP_READ, 0, 0, 0); |
1267 | if (ptr != NULL) | 1269 | if (ptr != NULL) |
1270 | { | ||
1271 | size = VirtualQuery (ptr, &mi, sizeof (mi)); | ||
1272 | if (size == 0) | ||
1273 | { | ||
1274 | UnmapViewOfFile (ptr); | ||
1275 | ptr = NULL; | ||
1276 | } | ||
1277 | else | ||
1278 | { | ||
1279 | size = mi.RegionSize; | ||
1280 | } | ||
1281 | } | ||
1282 | if (ptr != NULL) | ||
1268 | #endif | 1283 | #endif |
1269 | { | 1284 | { |
1270 | if ( ( (plugin->extractMethod != NULL) && | 1285 | if ( ( (plugin->extractMethod != NULL) && |
@@ -1382,20 +1397,32 @@ read_plugin_data (int fd) | |||
1382 | 1397 | ||
1383 | 1398 | ||
1384 | void CALLBACK | 1399 | void CALLBACK |
1385 | RundllEntryPoint(HWND hwnd, | 1400 | RundllEntryPoint (HWND hwnd, |
1386 | HINSTANCE hinst, | 1401 | HINSTANCE hinst, |
1387 | LPSTR lpszCmdLine, | 1402 | LPSTR lpszCmdLine, |
1388 | int nCmdShow) | 1403 | int nCmdShow) |
1389 | { | 1404 | { |
1390 | int in; | 1405 | intptr_t in_h; |
1391 | int out; | 1406 | intptr_t out_h; |
1407 | int in, out; | ||
1392 | 1408 | ||
1393 | sscanf(lpszCmdLine, "%u %u", &in, &out); | 1409 | sscanf(lpszCmdLine, "%lu %lu", &in_h, &out_h); |
1410 | in = _open_osfhandle (in_h, _O_RDONLY); | ||
1411 | out = _open_osfhandle (out_h, 0); | ||
1394 | setmode (in, _O_BINARY); | 1412 | setmode (in, _O_BINARY); |
1395 | setmode (out, _O_BINARY); | 1413 | setmode (out, _O_BINARY); |
1396 | process_requests (read_plugin_data (in), | 1414 | process_requests (read_plugin_data (in), |
1397 | in, out); | 1415 | in, out); |
1398 | } | 1416 | } |
1417 | |||
1418 | void CALLBACK | ||
1419 | RundllEntryPointA (HWND hwnd, | ||
1420 | HINSTANCE hinst, | ||
1421 | LPSTR lpszCmdLine, | ||
1422 | int nCmdShow) | ||
1423 | { | ||
1424 | return RundllEntryPoint(hwnd, hinst, lpszCmdLine, nCmdShow); | ||
1425 | } | ||
1399 | #endif | 1426 | #endif |
1400 | 1427 | ||
1401 | 1428 | ||
@@ -1405,58 +1432,123 @@ RundllEntryPoint(HWND hwnd, | |||
1405 | static void | 1432 | static void |
1406 | start_process (struct EXTRACTOR_PluginList *plugin) | 1433 | start_process (struct EXTRACTOR_PluginList *plugin) |
1407 | { | 1434 | { |
1435 | #if !WINDOWS | ||
1408 | int p1[2]; | 1436 | int p1[2]; |
1409 | int p2[2]; | 1437 | int p2[2]; |
1410 | pid_t pid; | 1438 | pid_t pid; |
1411 | int status; | 1439 | int status; |
1412 | #ifdef WINDOWS | ||
1413 | HANDLE process; | ||
1414 | #endif | ||
1415 | 1440 | ||
1416 | #ifndef WINDOWS | ||
1417 | plugin->cpid = -1; | 1441 | plugin->cpid = -1; |
1418 | if (0 != pipe (p1)) | 1442 | if (0 != pipe (p1)) |
1419 | #else | ||
1420 | plugin->hProcess = NULL; | ||
1421 | if (0 != _pipe (p1, 0, _O_BINARY)) | ||
1422 | #endif | ||
1423 | { | 1443 | { |
1424 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | 1444 | plugin->flags = EXTRACTOR_OPTION_DISABLED; |
1425 | return; | 1445 | return; |
1426 | } | 1446 | } |
1427 | #ifndef WINDOWS | ||
1428 | if (0 != pipe (p2)) | 1447 | if (0 != pipe (p2)) |
1429 | #else | ||
1430 | if (0 != _pipe (p2, 0, _O_BINARY)) | ||
1431 | #endif | ||
1432 | { | 1448 | { |
1433 | close (p1[0]); | 1449 | close (p1[0]); |
1434 | close (p1[1]); | 1450 | close (p1[1]); |
1435 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | 1451 | plugin->flags = EXTRACTOR_OPTION_DISABLED; |
1436 | return; | 1452 | return; |
1437 | } | 1453 | } |
1438 | #ifndef WINDOWS | ||
1439 | pid = fork (); | 1454 | pid = fork (); |
1440 | plugin->cpid = pid; | 1455 | plugin->cpid = pid; |
1441 | if (pid == -1) | 1456 | if (pid == -1) |
1457 | { | ||
1458 | close (p1[0]); | ||
1459 | close (p1[1]); | ||
1460 | close (p2[0]); | ||
1461 | close (p2[1]); | ||
1462 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1463 | return; | ||
1464 | } | ||
1465 | if (pid == 0) | ||
1466 | { | ||
1467 | close (p1[1]); | ||
1468 | close (p2[0]); | ||
1469 | process_requests (plugin, p1[0], p2[1]); | ||
1470 | _exit (0); | ||
1471 | } | ||
1472 | close (p1[0]); | ||
1473 | close (p2[1]); | ||
1474 | plugin->cpipe_in = fdopen (p1[1], "w"); | ||
1475 | if (plugin->cpipe_in == NULL) | ||
1476 | { | ||
1477 | perror ("fdopen"); | ||
1478 | (void) kill (plugin->cpid, SIGKILL); | ||
1479 | waitpid (plugin->cpid, &status, 0); | ||
1480 | close (p1[1]); | ||
1481 | close (p2[0]); | ||
1482 | plugin->cpid = -1; | ||
1483 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1484 | return; | ||
1485 | } | ||
1486 | plugin->cpipe_out = p2[0]; | ||
1442 | #else | 1487 | #else |
1488 | int p1[2]; | ||
1489 | int p2[2]; | ||
1443 | STARTUPINFO startup; | 1490 | STARTUPINFO startup; |
1444 | PROCESS_INFORMATION proc; | 1491 | PROCESS_INFORMATION proc; |
1445 | char cmd[100]; | 1492 | char cmd[MAX_PATH + 1]; |
1446 | char arg1[10], arg2[10]; | 1493 | char arg1[10], arg2[10]; |
1494 | HANDLE p10_os = INVALID_HANDLE_VALUE, p21_os = INVALID_HANDLE_VALUE; | ||
1495 | HANDLE p10_os_inh = INVALID_HANDLE_VALUE, p21_os_inh = INVALID_HANDLE_VALUE; | ||
1496 | |||
1497 | plugin->hProcess = NULL; | ||
1498 | if (0 != _pipe (p1, 0, _O_BINARY)) | ||
1499 | { | ||
1500 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1501 | return; | ||
1502 | } | ||
1503 | if (0 != _pipe (p2, 0, _O_BINARY)) | ||
1504 | { | ||
1505 | close (p1[0]); | ||
1506 | close (p1[1]); | ||
1507 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1508 | return; | ||
1509 | } | ||
1447 | 1510 | ||
1448 | memset (&startup, 0, sizeof (STARTUPINFO)); | 1511 | memset (&startup, 0, sizeof (STARTUPINFO)); |
1449 | write_plugin_data (p1[1], plugin); | ||
1450 | 1512 | ||
1451 | sprintf(cmd, "libextractor-3.dll,RundllEntryPoint@16 %u %u", p1[0], p1[1]); | 1513 | p10_os = (HANDLE) _get_osfhandle (p1[0]); |
1452 | if (CreateProcess("rundll32.exe", "libextractor-3.dll,RundllEntryPoint@16", NULL, NULL, TRUE, 0, NULL, NULL, | 1514 | p21_os = (HANDLE) _get_osfhandle (p2[1]); |
1515 | |||
1516 | if (p10_os == INVALID_HANDLE_VALUE || p21_os == INVALID_HANDLE_VALUE) | ||
1517 | { | ||
1518 | close (p1[0]); | ||
1519 | close (p1[1]); | ||
1520 | close (p2[0]); | ||
1521 | close (p2[1]); | ||
1522 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1523 | return; | ||
1524 | } | ||
1525 | |||
1526 | if (!DuplicateHandle (GetCurrentProcess (), p10_os, GetCurrentProcess (), | ||
1527 | &p10_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS) | ||
1528 | || !DuplicateHandle (GetCurrentProcess (), p21_os, GetCurrentProcess (), | ||
1529 | &p21_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS)) | ||
1530 | { | ||
1531 | if (p10_os_inh != INVALID_HANDLE_VALUE) | ||
1532 | CloseHandle (p10_os_inh); | ||
1533 | if (p21_os_inh != INVALID_HANDLE_VALUE) | ||
1534 | CloseHandle (p21_os_inh); | ||
1535 | close (p1[0]); | ||
1536 | close (p1[1]); | ||
1537 | close (p2[0]); | ||
1538 | close (p2[1]); | ||
1539 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | ||
1540 | return; | ||
1541 | } | ||
1542 | |||
1543 | snprintf(cmd, MAX_PATH + 1, "rundll32.exe libextractor-3.dll,RundllEntryPoint@16 %lu %lu", p10_os_inh, p21_os_inh); | ||
1544 | cmd[MAX_PATH] = '\0'; | ||
1545 | if (CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, | ||
1453 | &startup, &proc)) | 1546 | &startup, &proc)) |
1454 | { | 1547 | { |
1455 | plugin->hProcess = proc.hProcess; | 1548 | plugin->hProcess = proc.hProcess; |
1456 | CloseHandle (proc.hThread); | 1549 | CloseHandle (proc.hThread); |
1457 | } | 1550 | } |
1458 | else | 1551 | else |
1459 | #endif | ||
1460 | { | 1552 | { |
1461 | close (p1[0]); | 1553 | close (p1[0]); |
1462 | close (p1[1]); | 1554 | close (p1[1]); |
@@ -1465,40 +1557,28 @@ start_process (struct EXTRACTOR_PluginList *plugin) | |||
1465 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | 1557 | plugin->flags = EXTRACTOR_OPTION_DISABLED; |
1466 | return; | 1558 | return; |
1467 | } | 1559 | } |
1468 | #ifndef WINDOWS | ||
1469 | if (pid == 0) | ||
1470 | { | ||
1471 | close (p1[1]); | ||
1472 | close (p2[0]); | ||
1473 | process_requests (plugin, p1[0], p2[1]); | ||
1474 | _exit (0); | ||
1475 | } | ||
1476 | #endif | ||
1477 | close (p1[0]); | 1560 | close (p1[0]); |
1478 | close (p2[1]); | 1561 | close (p2[1]); |
1562 | CloseHandle (p10_os_inh); | ||
1563 | CloseHandle (p21_os_inh); | ||
1564 | |||
1565 | write_plugin_data (p1[1], plugin); | ||
1566 | |||
1479 | plugin->cpipe_in = fdopen (p1[1], "w"); | 1567 | plugin->cpipe_in = fdopen (p1[1], "w"); |
1480 | if (plugin->cpipe_in == NULL) | 1568 | if (plugin->cpipe_in == NULL) |
1481 | { | 1569 | { |
1482 | perror ("fdopen"); | 1570 | perror ("fdopen"); |
1483 | #ifndef WINDOWS | ||
1484 | (void) kill (plugin->cpid, SIGKILL); | ||
1485 | waitpid (plugin->cpid, &status, 0); | ||
1486 | #else | ||
1487 | TerminateProcess (plugin->hProcess, 0); | 1571 | TerminateProcess (plugin->hProcess, 0); |
1488 | WaitForSingleObject (process, INFINITE); | 1572 | WaitForSingleObject (plugin->hProcess, INFINITE); |
1489 | CloseHandle (plugin->hProcess); | 1573 | CloseHandle (plugin->hProcess); |
1490 | #endif | ||
1491 | close (p1[1]); | 1574 | close (p1[1]); |
1492 | close (p2[0]); | 1575 | close (p2[0]); |
1493 | #ifndef WINDOWS | ||
1494 | plugin->cpid = -1; | ||
1495 | #else | ||
1496 | plugin->hProcess = INVALID_HANDLE_VALUE; | 1576 | plugin->hProcess = INVALID_HANDLE_VALUE; |
1497 | #endif | ||
1498 | plugin->flags = EXTRACTOR_OPTION_DISABLED; | 1577 | plugin->flags = EXTRACTOR_OPTION_DISABLED; |
1499 | return; | 1578 | return; |
1500 | } | 1579 | } |
1501 | plugin->cpipe_out = p2[0]; | 1580 | plugin->cpipe_out = p2[0]; |
1581 | #endif | ||
1502 | } | 1582 | } |
1503 | 1583 | ||
1504 | 1584 | ||
@@ -1650,7 +1730,6 @@ make_shm (int is_tail, | |||
1650 | #ifndef WINDOWS | 1730 | #ifndef WINDOWS |
1651 | int *shmid, | 1731 | int *shmid, |
1652 | #else | 1732 | #else |
1653 | HANDLE *mappedFile, | ||
1654 | HANDLE *map, | 1733 | HANDLE *map, |
1655 | #endif | 1734 | #endif |
1656 | char *fn, | 1735 | char *fn, |
@@ -1658,10 +1737,10 @@ make_shm (int is_tail, | |||
1658 | size_t size) | 1737 | size_t size) |
1659 | { | 1738 | { |
1660 | const char *tpath; | 1739 | const char *tpath; |
1661 | |||
1662 | #ifdef WINDOWS | 1740 | #ifdef WINDOWS |
1663 | tpath = "%TEMP%\\"; | 1741 | tpath = "Local\\"; |
1664 | #elif SOMEBSD | 1742 | #elif SOMEBSD |
1743 | const char *tpath; | ||
1665 | /* this works on FreeBSD, not sure about others... */ | 1744 | /* this works on FreeBSD, not sure about others... */ |
1666 | tpath = getenv ("TMPDIR"); | 1745 | tpath = getenv ("TMPDIR"); |
1667 | if (tpath == NULL) | 1746 | if (tpath == NULL) |
@@ -1692,16 +1771,11 @@ make_shm (int is_tail, | |||
1692 | } | 1771 | } |
1693 | return 0; | 1772 | return 0; |
1694 | #else | 1773 | #else |
1695 | *mappedFile = CreateFile (fn, | 1774 | *map = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, fn); |
1696 | GENERIC_READ | GENERIC_WRITE, | 1775 | *ptr = MapViewOfFile (*map, FILE_MAP_WRITE, 0, 0, size); |
1697 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, | 1776 | if (*ptr == NULL) |
1698 | FILE_FLAG_DELETE_ON_CLOSE, NULL); | ||
1699 | *map = CreateFileMapping (*mappedFile, NULL, PAGE_READWRITE, 1, 0, NULL); | ||
1700 | ptr = MapViewOfFile (*map, FILE_MAP_READ, 0, 0, 0); | ||
1701 | if (ptr == NULL) | ||
1702 | { | 1777 | { |
1703 | CloseHandle (*map); | 1778 | CloseHandle (*map); |
1704 | CloseHandle (*mappedFile); | ||
1705 | return 1; | 1779 | return 1; |
1706 | } | 1780 | } |
1707 | return 0; | 1781 | return 0; |
@@ -1742,9 +1816,7 @@ extract (struct EXTRACTOR_PluginList *plugins, | |||
1742 | int tshmid; | 1816 | int tshmid; |
1743 | #else | 1817 | #else |
1744 | HANDLE map; | 1818 | HANDLE map; |
1745 | HANDLE mappedFile; | ||
1746 | HANDLE tmap; | 1819 | HANDLE tmap; |
1747 | HANDLE tmappedFile; | ||
1748 | #endif | 1820 | #endif |
1749 | 1821 | ||
1750 | want_shm = 0; | 1822 | want_shm = 0; |
@@ -1790,7 +1862,6 @@ extract (struct EXTRACTOR_PluginList *plugins, | |||
1790 | #ifndef WINDOWS | 1862 | #ifndef WINDOWS |
1791 | &shmid, | 1863 | &shmid, |
1792 | #else | 1864 | #else |
1793 | &mappedFile, | ||
1794 | &map, | 1865 | &map, |
1795 | #endif | 1866 | #endif |
1796 | fn, sizeof(fn), size)) | 1867 | fn, sizeof(fn), size)) |
@@ -1802,7 +1873,6 @@ extract (struct EXTRACTOR_PluginList *plugins, | |||
1802 | #ifndef WINDOWS | 1873 | #ifndef WINDOWS |
1803 | &tshmid, | 1874 | &tshmid, |
1804 | #else | 1875 | #else |
1805 | &tmappedFile, | ||
1806 | &tmap, | 1876 | &tmap, |
1807 | #endif | 1877 | #endif |
1808 | tfn, sizeof(tfn), tsize)) ) | 1878 | tfn, sizeof(tfn), tsize)) ) |
@@ -1924,12 +1994,10 @@ extract (struct EXTRACTOR_PluginList *plugins, | |||
1924 | #else | 1994 | #else |
1925 | UnmapViewOfFile (ptr); | 1995 | UnmapViewOfFile (ptr); |
1926 | CloseHandle (map); | 1996 | CloseHandle (map); |
1927 | CloseHandle (mappedFile); | ||
1928 | if (tptr != NULL) | 1997 | if (tptr != NULL) |
1929 | { | 1998 | { |
1930 | UnmapViewOfFile (tptr); | 1999 | UnmapViewOfFile (tptr); |
1931 | CloseHandle (tmap); | 2000 | CloseHandle (tmap); |
1932 | CloseHandle (tmappedFile); | ||
1933 | } | 2001 | } |
1934 | #endif | 2002 | #endif |
1935 | } | 2003 | } |