1398
const char *dir,
1399
int prepend_cmd, int fhin, int fhout, int fherr)
1400
{
1401
- STARTUPINFOW si;
1401
+ static int restrict_handle_inheritance = 1;
1402
+ STARTUPINFOEXW si;
1403
PROCESS_INFORMATION pi;
1404
+ LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
1405
+ HANDLE stdhandles[3];
1406
+ DWORD stdhandles_count = 0;
1407
+ SIZE_T size;
1408
struct strbuf args;
1409
wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
1410
unsigned flags = CREATE_UNICODE_ENVIRONMENT;
1440
CloseHandle(cons);
1441
}
1442
memset(&si, 0, sizeof(si));
1438
- si.cb = sizeof(si);
1439
- si.dwFlags = STARTF_USESTDHANDLES;
1440
- si.hStdInput = winansi_get_osfhandle(fhin);
1441
- si.hStdOutput = winansi_get_osfhandle(fhout);
1442
- si.hStdError = winansi_get_osfhandle(fherr);
1443
+ si.StartupInfo.cb = sizeof(si);
1444
+ si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
1445
+ si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
1446
+ si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
1447
+
1448
+ /* The list of handles cannot contain duplicates */
1449
+ if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
1450
+ stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
1451
+ if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
1452
+ si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
1453
+ stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
1454
+ if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
1455
+ si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
1456
+ si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
1457
+ stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
1458
+ if (stdhandles_count)
1459
+ si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
1460
1461
if (*argv && !strcmp(cmd, *argv))
1462
wcmd[0] = L'\0';
1489
wenvblk = make_environment_block(deltaenv);
1490
1491
memset(&pi, 0, sizeof(pi));
1475
- ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL, TRUE,
1476
- flags, wenvblk, dir ? wdir : NULL, &si, &pi);
1492
+ if (restrict_handle_inheritance && stdhandles_count &&
1493
+ (InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
1494
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
1495
+ (attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
1496
+ (HeapAlloc(GetProcessHeap(), 0, size))) &&
1497
+ InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
1498
+ UpdateProcThreadAttribute(attr_list, 0,
1499
+ PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
1500
+ stdhandles,
1501
+ stdhandles_count * sizeof(HANDLE),
1502
+ NULL, NULL)) {
1503
+ si.lpAttributeList = attr_list;
1504
+ flags |= EXTENDED_STARTUPINFO_PRESENT;
1505
+ }
1506
+
1507
+ ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1508
+ stdhandles_count ? TRUE : FALSE,
1509
+ flags, wenvblk, dir ? wdir : NULL,
1510
+ &si.StartupInfo, &pi);
1511
+
1512
+ /*
1513
+ * On Windows 2008 R2, it seems that specifying certain types of handles
1514
+ * (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
1515
+ * error. Rather than playing finicky and fragile games, let's just try
1516
+ * to detect this situation and simply try again without restricting any
1517
+ * handle inheritance. This is still better than failing to create
1518
+ * processes.
1519
+ */
1520
+ if (!ret && restrict_handle_inheritance && stdhandles_count) {
1521
+ DWORD err = GetLastError();
1522
+ struct strbuf buf = STRBUF_INIT;
1523
+
1524
+ if (err != ERROR_NO_SYSTEM_RESOURCES &&
1525
+ /*
1526
+ * On Windows 7 and earlier, handles on pipes and character
1527
+ * devices are inherited automatically, and cannot be
1528
+ * specified in the thread handle list. Rather than trying
1529
+ * to catch each and every corner case (and running the
1530
+ * chance of *still* forgetting a few), let's just fall
1531
+ * back to creating the process without trying to limit the
1532
+ * handle inheritance.
1533
+ */
1534
+ !(err == ERROR_INVALID_PARAMETER &&
1535
+ GetVersion() >> 16 < 9200) &&
1536
+ !getenv("SUPPRESS_HANDLE_INHERITANCE_WARNING")) {
1537
+ DWORD fl = 0;
1538
+ int i;
1539
+
1540
+ setenv("SUPPRESS_HANDLE_INHERITANCE_WARNING", "1", 1);
1541
+
1542
+ for (i = 0; i < stdhandles_count; i++) {
1543
+ HANDLE h = stdhandles[i];
1544
+ strbuf_addf(&buf, "handle #%d: %p (type %lx, "
1545
+ "handle info (%d) %lx\n", i, h,
1546
+ GetFileType(h),
1547
+ GetHandleInformation(h, &fl),
1548
+ fl);
1549
+ }
1550
+ strbuf_addstr(&buf, "\nThis is a bug; please report it "
1551
+ "at\nhttps://github.com/git-for-windows/"
1552
+ "git/issues/new\n\n"
1553
+ "To suppress this warning, please set "
1554
+ "the environment variable\n\n"
1555
+ "\tSUPPRESS_HANDLE_INHERITANCE_WARNING=1"
1556
+ "\n");
1557
+ }
1558
+ restrict_handle_inheritance = 0;
1559
+ flags &= ~EXTENDED_STARTUPINFO_PRESENT;
1560
+ ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1561
+ TRUE, flags, wenvblk, dir ? wdir : NULL,
1562
+ &si.StartupInfo, &pi);
1563
+ if (ret && buf.len) {
1564
+ errno = err_win_to_posix(GetLastError());
1565
+ warning("failed to restrict file handles (%ld)\n\n%s",
1566
+ err, buf.buf);
1567
+ }
1568
+ strbuf_release(&buf);
1569
+ } else if (!ret)
1570
+ errno = err_win_to_posix(GetLastError());
1571
+
1572
+ if (si.lpAttributeList)
1573
+ DeleteProcThreadAttributeList(si.lpAttributeList);
1574
+ if (attr_list)
1575
+ HeapFree(GetProcessHeap(), 0, attr_list);
1576
1577
free(wenvblk);
1578
free(wargs);
1579
1481
- if (!ret) {
1482
- errno = ENOENT;
1580
+ if (!ret)
1581
return -1;
1484
- }
1582
+
1583
CloseHandle(pi.hThread);
1584
1585
/*