Index: winsup/cygwin/ntdll.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/ntdll.h,v retrieving revision 1.58 diff -p -u -r1.58 ntdll.h --- winsup/cygwin/ntdll.h 29 Jul 2007 12:27:22 -0000 1.58 +++ winsup/cygwin/ntdll.h 30 Jul 2007 06:34:17 -0000 @@ -153,16 +153,62 @@ typedef struct _FILE_ID_BOTH_DIR_INFORMA typedef ULONG KAFFINITY; -typedef enum _SYSTEM_INFORMATION_CLASS -{ - SystemBasicInformation = 0, - SystemPerformanceInformation = 2, - SystemTimeOfDayInformation = 3, - SystemProcessesAndThreadsInformation = 5, - SystemProcessorTimes = 8, - SystemPagefileInformation = 18, - /* There are a lot more of these... */ -} SYSTEM_INFORMATION_CLASS; +typedef enum _SYSTEM_INFORMATION_CLASS { + SystemBasicInformation = 0, + SystemCpuInformation = 1, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, /* was SystemTimeInformation */ + SystemNotImplemented1 = 4, + SystemProcessesAndThreadsInformation = 5, + SystemCallCounts = 6, + SystemConfigurationInformation = 7, + SystemProcessorTimes = 8, + SystemGlobalFlag = 9, + SystemNotImplemented2 = 10, + SystemModuleInformation = 11, + SystemLockInformation = 12, + SystemNotImplemented3 = 13, + SystemNotImplemented4 = 14, + SystemNotImplemented5 = 15, + SystemHandleInformation = 16, + SystemObjectInformation = 17, + SystemPagefileInformation = 18, + SystemInstructionEmulationCounts = 19, + SystemInvalidInfoClass1 = 20, + SystemCacheInformation = 21, + SystemPoolTagInformation = 22, + SystemInterruptInformation = 23, + SystemDpcBehaviourInformation = 24, + SystemFullMemoryInformation = 25, + SystemNotImplemented6 = 25, + SystemLoadImage = 26, + SystemUnloadImage = 27, + SystemTimeAdjustmentInformation = 28, + SystemTimeAdjustment = 28, + SystemSummaryMemoryInformation = 29, + SystemNotImplemented7 = 29, + SystemNextEventIdInformation = 30, + SystemNotImplemented8 = 30, + SystemEventIdsInformation = 31, + SystemCrashDumpInformation = 32, + SystemExceptionInformation = 33, + SystemCrashDumpStateInformation = 34, + SystemKernelDebuggerInformation = 35, + SystemContextSwitchInformation = 36, + SystemRegistryQuotaInformation = 37, + SystemCurrentTimeZoneInformation = 44, + SystemTimeZoneInformation = 44, + SystemLookasideInformation = 45, + SystemSetTimeSlipEvent = 46, + SystemCreateSession = 47, + SystemDeleteSession = 48, + SystemInvalidInfoClass4 = 49, + SystemRangeStartInformation = 50, + SystemVerifierInformation = 51, + SystemAddVerifier = 52, + SystemSessionProcessesInformation = 53, + SystemInformationClassMax +} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_BASIC_INFORMATION { @@ -198,6 +244,29 @@ typedef struct __attribute__ ((aligned ( ULONG InterruptCount; } SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES; +/* FIXME: to be checked */ +#define MAXIMUM_FILENAME_LENGTH 256 + +typedef struct _SYSTEM_MODULE +{ + ULONG Reserved1; + ULONG Reserved2; + PVOID ImageBaseAddress; + ULONG ImageSize; + ULONG Flags; + WORD Id; + WORD Rank; + WORD Unknown; + WORD NameOffset; + BYTE Name[MAXIMUM_FILENAME_LENGTH]; +} SYSTEM_MODULE, *PSYSTEM_MODULE; + +typedef struct _SYSTEM_MODULE_INFORMATION +{ + ULONG ModulesCount; + SYSTEM_MODULE Modules[1]; /* FIXME: should be Modules[0] */ +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + typedef LONG KPRIORITY; typedef struct _VM_COUNTERS { Index: winsup/utils/Makefile.in =================================================================== RCS file: /cvs/src/src/winsup/utils/Makefile.in,v retrieving revision 1.66 diff -p -u -r1.66 Makefile.in --- winsup/utils/Makefile.in 10 Jul 2007 00:12:54 -0000 1.66 +++ winsup/utils/Makefile.in 30 Jul 2007 06:34:17 -0000 @@ -1,6 +1,6 @@ # Makefile for Cygwin utilities # Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006 Red Hat, Inc. +# 2005, 2006, 2007 Red Hat, Inc. # This file is part of Cygwin. @@ -99,15 +99,15 @@ else $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) endif -cygcheck.exe: cygcheck.o path.o dump_setup.o $(MINGW_DEP_LDLIBS) +cygcheck.exe: cygcheck.o bloda.o path.o dump_setup.o $(MINGW_DEP_LDLIBS) ifeq "$(libz)" "" @echo '*** Building cygcheck without package content checking due to missing mingw libz.a.' endif ifdef VERBOSE - $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) + $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll else - @echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz);\ - $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) + @echo $(CXX) -o $@ ${wordlist 1,4,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz) -lntdll;\ + $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll endif dumper.o: dumper.cc dumper.h @@ -150,6 +150,14 @@ else $(MINGW_CXX) $(zconf_h) $(zlib_h) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) $< endif +bloda.o: bloda.cc +ifdef VERBOSE + ${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $< +else + @echo $(MINGW_CXX) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) ... $^;\ + ${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $< +endif + cygcheck.o: cygcheck.cc ifdef VERBOSE ${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $< Index: winsup/utils/bloda.cc =================================================================== RCS file: winsup/utils/bloda.cc diff -N winsup/utils/bloda.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ winsup/utils/bloda.cc 30 Jul 2007 06:34:17 -0000 @@ -0,0 +1,410 @@ +/* bloda.cc + + Copyright 2007 Red Hat, Inc. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +#define cygwin_internal cygwin_internal_dontuse +#include +#include +#include +#include +#include +#undef cygwin_internal + +#define alloca __builtin_alloca + +#undef DEBUGGING +#ifdef DEBUGGING +#define dbg_printf(ARGS) printf ARGS +#else /* DEBUGGING */ +#define dbg_printf(ARGS) do { } while (0) +#endif /* DEBUGGING */ + + +VOID NTAPI (*pRtlFreeUnicodeString)(PUNICODE_STRING) = NULL; + +/* This module detects applications from the Big List of Dodgy Apps, + a list of applications that have at some given time been shown to + interfere with the operation of cygwin. It detects the presence of + applications on the system by looking for any of four traces an + installation might leave: 1) registry keys, 2) files on disk + 3) running executables 4) loaded dlls or drivers. + + At the time of writing, the BLODA amounts to:- + + Sonic Solutions burning software containing DLA component + Norton/MacAffee/Symantec antivirus or antispyware + Logitech webcam software with "Logitech process monitor" service + Kerio, Agnitum or ZoneAlarm Personal Firewall + Iolo System Mechanic/AntiVirus/Firewall + LanDesk + Windows Defender + Embassy Trust Suite fingerprint reader software containing wxvault.dll + +*/ + +enum bad_app { + SONIC, NORTON, MACAFFEE, SYMANTEC, + LOGITECH, KERIO, AGNITUM, ZONEALARM, + IOLO, LANDESK, WINDEFENDER, EMBASSYTS +}; + +struct bad_app_info { + enum bad_app app_id; + const char *details; + char found_it; +}; + +enum bad_app_det_method { + HKLMKEY, HKCUKEY, FILENAME, PROCESSNAME, HOOKDLLNAME +}; + +struct bad_app_det { + enum bad_app_det_method type; + const char *param; + enum bad_app app; +}; + +static const struct bad_app_det dodgy_app_detects[] = { + { PROCESSNAME, "dlactrlw.exe", SONIC }, + { HOOKDLLNAME, "wxvault.dll", EMBASSYTS }, + { HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\vsdatant", ZONEALARM }, + { FILENAME, "%windir%\\System32\\vsdatant.sys", ZONEALARM }, + { HKLMKEY, "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv", LOGITECH }, + { PROCESSNAME, "LVPrcSrv.exe", LOGITECH }, + { FILENAME, "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH }, +}; + +static const size_t num_of_detects = sizeof (dodgy_app_detects) / sizeof (dodgy_app_detects[0]); + +static struct bad_app_info big_list_of_dodgy_apps[] = { + { SONIC, "Sonic Solutions burning software containing DLA component" }, + { NORTON, "Norton antivirus or antispyware software" }, + { MACAFFEE, "Macaffee antivirus or antispyware software" }, + { SYMANTEC, "Symantec antivirus or antispyware software" }, + { LOGITECH, "Logitech Process Monitor service" }, + { KERIO, "Kerio Personal Firewall" }, + { AGNITUM, "Agnitum Personal Firewall" }, + { ZONEALARM, "ZoneAlarm Personal Firewall" }, + { IOLO, "Iolo System Mechanic/AntiVirus/Firewall software" }, + { LANDESK, "Landesk" }, + { WINDEFENDER, "Windows Defender" }, + { EMBASSYTS, "Embassy Trust Suite fingerprint reader software containing wxvault.dll" }, +}; + +static const size_t num_of_dodgy_apps = sizeof (big_list_of_dodgy_apps) / sizeof (big_list_of_dodgy_apps[0]); + +static PSYSTEM_PROCESSES +get_process_list (void) +{ + int n_procs = 0x100; + PSYSTEM_PROCESSES pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist); + + while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation, + pslist, n_procs * sizeof *pslist, 0) == STATUS_INFO_LENGTH_MISMATCH) + { + n_procs *= 2; + free (pslist); + pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist); + } + return pslist; +} + +static PSYSTEM_MODULE_INFORMATION +get_module_list (void) +{ + int n_mods = 0x100; + NTSTATUS rv; + PSYSTEM_MODULE_INFORMATION modlist = (PSYSTEM_MODULE_INFORMATION) malloc (n_mods * sizeof *modlist); + + while (1) + { + rv = NtQuerySystemInformation (SystemModuleInformation, + modlist, n_mods * sizeof *modlist, 0); + if (rv != STATUS_INFO_LENGTH_MISMATCH) + break; + n_mods *= 2; + free (modlist); + modlist = (PSYSTEM_MODULE_INFORMATION) malloc (n_mods * sizeof *modlist); + } + dbg_printf (("final status $%08x\n", (unsigned int) rv)); + return modlist; +} + +static bool +find_process_in_list (PSYSTEM_PROCESSES pslist, PUNICODE_STRING psname) +{ + while (1) + { + if (pslist->ProcessName.Length && pslist->ProcessName.Buffer) + { + dbg_printf (("%S\n", pslist->ProcessName.Buffer)); + if (!_wcsicmp (pslist->ProcessName.Buffer, psname->Buffer)) + return true; + } + if (!pslist->NextEntryDelta) + break; + pslist = (PSYSTEM_PROCESSES)(pslist->NextEntryDelta + (char *)pslist); + }; + return false; +} + +static bool +find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist, const char * const modname) +{ + ULONG cnt; + PSYSTEM_MODULE ptr = &modlist->Modules[0]; + for (cnt = modlist->ModulesCount; cnt; --cnt, ++ptr) + { + dbg_printf (("name '%s' offset %d ", &ptr->Name[0], ptr->NameOffset)); + dbg_printf (("= '%s'\n", &ptr->Name[ptr->NameOffset])); + if (!_stricmp ((char *)&ptr->Name[ptr->NameOffset], modname)) + return true; + } + return false; +} + +static bool +expand_path (const char *path, char *outbuf) +{ + char *dst = outbuf; + const char *end, *envval; + char envvar[MAX_PATH]; + size_t len; + + while ((dst - outbuf) < MAX_PATH) + { + if (*path != '%') + { + if ((*dst++ = *path++) != 0) + continue; + break; + } + /* Expand an environ var. */ + end = path + 1; + while (*end != '%') + { + /* Watch out for unterminated % */ + if (*end++ == 0) + { + end = NULL; + break; + } + } + /* If we didn't find the end, can't expand it. */ + if ((end == NULL) || (end == (path + 1))) + { + /* Unterminated % so copy verbatim. */ + *dst++ = *path++; + continue; + } + /* Expand the environment var into the new path. */ + if ((end - (path + 1)) >= MAX_PATH) + return -1; + memcpy (envvar, path + 1, end - (path + 1)); + envvar[end - (path + 1)] = 0; + envval = getenv (envvar); + /* If not found, copy env var name verbatim. */ + if (envval == NULL) + { + *dst++ = *path++; + continue; + } + /* Check enough room before copying. */ + len = strlen (envval); + if ((dst + len - outbuf) >= MAX_PATH) + return false; + memcpy (dst, envval, len); + dst += len; + /* And carry on past the end of env var name. */ + path = end + 1; + } + return (dst - outbuf) < MAX_PATH; +} + +static bool +detect_dodgy_app (const struct bad_app_det *det, PSYSTEM_PROCESSES pslist, PSYSTEM_MODULE_INFORMATION modlist) +{ + HANDLE fh; + HKEY hk; + UNICODE_STRING unicodename; + ANSI_STRING ansiname; + NTSTATUS rv; + bool found; + char expandedname[MAX_PATH]; + + switch (det->type) + { + case HKLMKEY: + dbg_printf (("Detect reg key hklm '%s'... ", det->param)); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS) + { + RegCloseKey (hk); + dbg_printf (("found!\n")); + return true; + } + break; + + case HKCUKEY: + dbg_printf (("Detect reg key hkcu '%s'... ", det->param)); + if (RegOpenKeyEx (HKEY_CURRENT_USER, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS) + { + RegCloseKey (hk); + dbg_printf (("found!\n")); + return true; + } + break; + + case FILENAME: + dbg_printf (("Detect filename '%s'... ", det->param)); + if (!expand_path (det->param, expandedname)) + { + printf ("Expansion failure!\n"); + break; + } + dbg_printf (("('%s' after expansion)... ", expandedname)); + fh = CreateFile (expandedname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE + | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); + if (fh != INVALID_HANDLE_VALUE) + { + CloseHandle (fh); + dbg_printf (("found!\n")); + return true; + } + break; + + case PROCESSNAME: + dbg_printf (("Detect proc name '%s'... ", det->param)); + /* Equivalent of RtlInitAnsiString. */ + ansiname.Length = ansiname.MaximumLength = strlen (det->param); + ansiname.Buffer = (CHAR *) det->param; + rv = RtlAnsiStringToUnicodeString (&unicodename, &ansiname, TRUE); + if (rv != STATUS_SUCCESS) + { + printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv); + break; + } + found = find_process_in_list (pslist, &unicodename); + if (!pRtlFreeUnicodeString) + pRtlFreeUnicodeString = (VOID NTAPI (*)(PUNICODE_STRING)) GetProcAddress (LoadLibrary ("ntdll.dll"), "RtlFreeUnicodeString"); + if (pRtlFreeUnicodeString) + pRtlFreeUnicodeString (&unicodename); + else + printf ("leaking mem...oops\n"); + if (found) + { + dbg_printf (("found!\n")); + return true; + } + break; + + case HOOKDLLNAME: + dbg_printf (("Detect hookdll '%s'... ", det->param)); + if (find_module_in_list (modlist, det->param)) + { + dbg_printf (("found!\n")); + return true; + } + break; + + } + dbg_printf (("not found.\n")); + return false; +} + +/* Wish we could use C99 member initialisers to get array in order. */ +static struct bad_app_info * +find_dodgy_app_info (enum bad_app which_app) +{ + size_t i; + for (i = 0; i < num_of_dodgy_apps; i++) + { + if (big_list_of_dodgy_apps[i].app_id == which_app) + return &big_list_of_dodgy_apps[i]; + } + return NULL; +} + + +void +dump_dodgy_apps (int verbose) +{ + size_t i, n_det = 0; + PSYSTEM_PROCESSES pslist; + PSYSTEM_MODULE_INFORMATION modlist; + + /* Read system info for detect testing. */ + pslist = get_process_list (); + modlist = get_module_list (); + + /* Go with builtin list for now; later may enhance to + read dodgy apps from a file or download from an URL. */ + for (i = 0; i < num_of_dodgy_apps; i++) + { + big_list_of_dodgy_apps[i].found_it = false; + } + + for (i = 0; i < num_of_detects; i++) + { + const struct bad_app_det *det = &dodgy_app_detects[i]; + struct bad_app_info *found = find_dodgy_app_info (det->app); + bool detected = detect_dodgy_app (det, pslist, modlist); + + /* Not found would mean we coded the lists bad. */ + assert (found); + if (detected) + { + ++n_det; + found->found_it |= (1 << det->type); + } + } + if (n_det) + { + printf ("\nPotential app conflicts:\n\n"); + for (i = 0; i < num_of_dodgy_apps; i++) + { + if (big_list_of_dodgy_apps[i].found_it) + { + printf ("%s%s", big_list_of_dodgy_apps[i].details, + verbose ? "\nDetected: " : ".\n"); + if (!verbose) + continue; + const char *sep = ""; + if (big_list_of_dodgy_apps[i].found_it & (1 << HKLMKEY)) + { + printf ("HKLM Registry Key"); + sep = ", "; + } + if (big_list_of_dodgy_apps[i].found_it & (1 << HKCUKEY)) + { + printf ("%sHKCU Registry Key", sep); + sep = ", "; + } + if (big_list_of_dodgy_apps[i].found_it & (1 << FILENAME)) + { + printf ("%sNamed file", sep); + sep = ", "; + } + if (big_list_of_dodgy_apps[i].found_it & (1 << PROCESSNAME)) + { + printf ("%sNamed process", sep); + sep = ", "; + } + if (big_list_of_dodgy_apps[i].found_it & (1 << HOOKDLLNAME)) + { + printf ("%sLoaded hook DLL", sep); + } + printf (".\n\n"); + } + } + } + /* Tidy up allocations. */ + free (pslist); + free (modlist); +} + Index: winsup/utils/cygcheck.cc =================================================================== RCS file: /cvs/src/src/winsup/utils/cygcheck.cc,v retrieving revision 1.95 diff -p -u -r1.95 cygcheck.cc --- winsup/utils/cygcheck.cc 4 Jun 2007 01:57:16 -0000 1.95 +++ winsup/utils/cygcheck.cc 30 Jul 2007 06:34:17 -0000 @@ -50,9 +50,13 @@ typedef long long longlong; typedef __int64 longlong; #endif +/* In dump_setup.cc */ void dump_setup (int, char **, bool); void package_find (int, char **); void package_list (int, char **); +/* In bloda.cc */ +void dump_dodgy_apps (int verbose); + static const char version[] = "$Revision: 1.95 $"; @@ -1623,6 +1627,8 @@ dump_sysinfo () if (!cygwin_dll_count) puts ("Warning: cygwin1.dll not found on your path"); + dump_dodgy_apps (verbose); + if (is_nt) dump_sysinfo_services (); }