Вопрос по NtQueryObject Deadlock

Тема в разделе "WASM.WIN32", создана пользователем Viewsight, 9 ноя 2004.

  1. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Все нормально листает Handle но на фукции NtQueryObject

    в services.exe

    виснет тут


    Код (Text):
    1. ::services.exe-----------------------
    2. 821CA540 0010 100020  2   2   1    1 File           \Device\HarddiskVolume1\WINDOWS\system32
    3. 82250938 01e0 12019f  0   0   1    2 File           \Device\NamedPipe\ntsvcs
    4. 815B8028 01e4 12019f  0   0   1    2 File           \Device\NamedPipe\ntsvcs
    5. 81B35850 01ec 12019f  0   0   1    2 File           \Device\NamedPipe\ntsvcs
    6. 81B0A820 020c 12019f  0   0   1    1 File           \Device\NamedPipe\scerpc
    7. 81B58D38 0210 12019f  0   0   1    2 File           \Device\NamedPipe\scerpc
    8. 81ACA2E0 0224 100001  0   0   1    1 File           \Device\KsecDD
    9. 813CC5B0 0244 12019f  0   0   1    2 File           \Device\NamedPipe\ntsvcs
    10. 81BF89E8 0250 1a019f  0   0   1    1 File           \Device\NamedPipe\net\NtControlPipe1
    11. 81B39338 0268 12019f  0   0   1    1 File           \Device\NamedPipe\ntsvcs
    12. 81AA8AA0 026c 12019f  0   0   1    3 File




    тут по идее должен быть "\Device\NamedPipe\net\NtControlPipe1"



    КОД:


    Код (Text):
    1. while (NtQuerySystemInformation(NT::SystemHandleInformation,
    2. p, n * sizeof (*p), &Ret)
    3. == STATUS_INFO_LENGTH_MISMATCH)
    4. delete [] p, p = new ULONG[n *= 2];
    5.  
    6. ProcList_Create(&Proc_List);
    7.  
    8. NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p);
    9. lplp=Proc_List.lpList;
    10. lplp=lplp->Next;
    11. for (ULONG PCount=0;PCount<Proc_List.dwCount;PCount++)
    12. {
    13.     printf("::%s----------------------- \n",lplp->szName);
    14.     for (ULONG i = 0; i < h->uCount; i++)
    15.     {
    16.         if(h->aSH[i].uIdProcess==lplp->dwID)
    17.         {
    18.            
    19.             if (h->aSH[i].ObjectType==28)//File Object
    20.             {
    21.                
    22.                 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, h->aSH[i].uIdProcess);
    23.  
    24.                     if (hProcess==NULL)
    25.                         continue;
    26.        
    27.                     NT::OBJECT_BASIC_INFORMATION obi;
    28.        
    29.                     if (NT::NtDuplicateObject(hProcess, HANDLE(h->aSH[i].Handle),
    30.                         NtCurrentProcess(), &hObject,
    31.                         0, 0, DUPLICATE_SAME_ATTRIBUTES)
    32.                         != STATUS_SUCCESS)
    33.                         continue;
    34.                 NT::NtQueryObject(hObject, NT::ObjectBasicInformation,
    35.                     &obi, sizeof obi, &n);
    36.  
    37.                 printf("%p %04hx %6lx %2x %3lx %3ld %4ld ",
    38.                     h->aSH[i].pObject, h->aSH[i].Handle, h->aSH[i].GrantedAccess,
    39.                     int(h->aSH[i].Flags), obi.Attributes,
    40.                     obi.HandleCount - 1, obi.PointerCount - 2);
    41.  
    42.             n = obi.TypeInformationLength + 2;
    43.             NT::POBJECT_TYPE_INFORMATION oti = NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);
    44.  
    45.             rv = NT::NtQueryObject(hObject, NT::ObjectTypeInformation,
    46.                     oti, n, &n);
    47.         if (NT_SUCCESS(rv))
    48.             printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
    49.  
    50.         n = obi.NameInformationLength == 0
    51.         ? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
    52.  
    53.         NT::POBJECT_NAME_INFORMATION oni
    54.         = NT::POBJECT_NAME_INFORMATION(new CHAR[n]);
    55.  
    56.         rv = NT::NtQueryObject(hObject,
    57.         NT::ObjectNameInformation,
    58.         oni, n, &n);
    59.        
    60.  
    61.         if (NT_SUCCESS(rv))
    62.             printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
    63.             printf("\n");
    64.        
    65.         if (!(obi.Attributes&(0x02|0x01)))//для inheried and protected from close
    66.             NT::NtClose(hObject);
    67.  
    68.                 CloseHandle(hProcess);
    69.                 }
    70.         }
    71.     }
    72.     lplp=lplp->Next;
     
  2. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Да к стати! а виснет (уходит в себя) при вызове



    rv = NT::NtQueryObject(hObject, NT::ObjectTypeInformation,

    oti, n, &n);
     
  3. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Обычно это случается, при попытке получения имени именованного пайпа по хендлу. Но, похоже при других операциях тоже. Вобщем, трабла в том, что если пайп синхронный, то все операции то ли в очередь ставятся, то ли одним потоком обрабатываются. И если пайп уже чего-то делает и эта операция не завершена, то попытка получить имя пайпа завесит поток, до тех пор, пока пайп не закончит незавершенную операцию, а это может продолжаться очень долго. Это известная трабла. Многие на эти грабли наступали, даже гуру. Например, если ProcessExplorer'ом попытаться редактнуть DACL у "\Device\NamedPipe\net\NtControlPipe1", то он тоже виснет.



    В аттаче прога. Там эта проблема решается созданием отдельного потока и его убийством. Но это зело плохое решение. Недавно ElicZ выложил ImgList. Код ещё руки не дошли посмотреть, то в ридми он пишет, что, вроде, нашел решение. http://www.anticracking.sk/ElicZ



    [​IMG] _231279434__Hmz.rar
     
  4. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Выбрал таки минутку, посмотрел. Я думал Радим что-нить дельное придумал, а там то же убийство потока. Правда, ещё стек освобождается, но это и так понятно.
     
  5. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Обычно это случается, при попытке получения имени именованного пайпа по хендлу. Но, похоже при других операциях тоже.



    Мне фраза понравилась :) В переводе на русский язык означает "кирдык тебе в любом случае" :))))
     
  6. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Спасибо Four-F разобрался, это было к вопросу о чтении файла открытого в эксклюзивном доступе...



    Единственное что меня смущает это то что при выходе из программы она вешается да так что её таск манагер даже не удаляет, причём это происходит только под XP. А под 2003 сервером даже и не думает вешаться. Первый раз такое вижу... Что бы это могло быть? никаких вроде Эксепшенов нет...
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Затрудняюсь что-либо сказать. Попробуй посмотреть ProcessExplorer'ом, что там с потоками.
     
  8. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Поток один ибо алгоритм всё тот же - прибитие потока

    Я проверил процесс начинает зависать когда прибивается хотя бы один поток с "мертвым" обращением к Пайпу....



    В PE KeyedEvent=kernelObject\CritSecOutOfMemoryEvent

    3 iocompletisoona ....

    Я выложил два файла

    1. OpenE.exe <PATHNAME> - Открывает в эксулюзиве файл

    и лочит его.

    2. CA.exe <Pathname1> <PathName2> - копирует до 65536 (моё ограничение) первых байт из <Pathname1> - в <PathName2>

    Если <PathName1> - открыт в эксклюзиве...



    Напомню процесс виснет только под XP, а под 2003 всё в порядке...



    [​IMG] _1436316470__Ca.zip
     
  9. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Я, точнее ProcessExplorer, вижу несколько потоков. Все они чего-то ждут в NtQueryObject.



    kernelObject\CritSecOutOfMemoryEvent тут, наверное, не при чём. Он во всех процессах открывается.



    Разбирайся.



    [​IMG] 1149859551__ca.gif
     
  10. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Я проверил это те самые потоки которые были завершены

    TerminateThread - ом и считались зависшими...

    вот код:
    Код (Text):
    1.  
    2. .......
    3. hThread=CreateThread (NULL,0,(LPTHREAD_START_ROUTINE)GetObjectName,&ON,0,&tid);
    4.                
    5.                 if (WaitForSingleObject(hThread, 500) == WAIT_TIMEOUT)
    6.                 {
    7.    
    8.                         TerminateThread (hThread, 0);
    9.                    
    10.                 }
    11. GetExitCodeThread(hThread,&n);
    12.  
    13. CloseHandle(hThread);
    14. .....
    15.  




    А вот функция
    Код (Text):
    1.  
    2.  
    3. DWORD GetObjectName (POBJECT_NAME pon)
    4. {
    5.     return  NT::NtQueryObject(pon->hObject, NT::ObjectNameInformation, pon->oni, pon->MaxNameLenght, &pon->MaxNameLenght);
    6. }
    7.  




    Может я неправильно его терминейтю? .... хотя

    "Терминатор" в 2003 срабатывает как надо а в XP

    видимо нет...
     
  11. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    TerminateThread (hThread, 0);

    выполняется без ошибки....

    Но может быть дело в этом?

    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:







    If the target thread owns a critical section, the critical section will not be released.

    If the target thread is allocating memory from the heap, the heap lock will not be released.

    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.

    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.



    Как это обойти?
     
  12. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Код (Text):
    1.         THREAD 81478020  Cid 0624.08e4  Teb: 7ffaa000 Win32Thread: 00000000 WAIT: (Executive) KernelMode Non-Alertable
    2.             <font color="red]81368fdc  SynchronizationEvent</font><!--color-->
    3.         Not impersonating
    4.         DeviceMap                 e17c7008
    5.         Owning Process            80e4f950
    6.         Wait Start TickCount      740741         Elapsed Ticks: 681623
    7.         Context Switch Count      6
    8.         UserTime                  00:00:00.0000
    9.         KernelTime                00:00:00.0000
    10.         Start Address kernel32!OpenConsoleW (0x77e802f4)
    11.         Win32 Start Address 0x00401080
    12.         Stack Init ed689000 Current ed6889d8 Base ed689000 Limit ed686000 Call 0
    13.         Priority 12 BasePriority 8 PriorityDecrement 2 DecrementCount 16
    14.         ChildEBP RetAddr
    15.         ed6889f0 804ea71c nt!KiSwapContext+0x2e (FPO: [EBP 0xed688a24] [0,0,4])
    16.         ed6889fc 804ea5a3 nt!KiSwapThread+0x44 (FPO: [0,0,2])
    17.         <font color="red]ed688a24 8054daf6 nt!KeWaitForSingleObject+0x1c0</font><!--color--> (FPO: [Non-Fpo])
    18.         ed688a50 805bcb2a nt!IopAcquireFileObjectLock+0x4c (FPO: [Non-Fpo])
    19.         ed688a90 80576de7 nt!IopQueryXxxInformation+0x46 (FPO: [Non-Fpo])
    20.         ed688ab0 805755fd nt!IoQueryFileInformation+0x19 (FPO: [Non-Fpo])
    21.         ed688b24 805756af nt!IopQueryNameInternal+0x1af (FPO: [Non-Fpo])
    22.         ed688b44 80575154 nt!IopQueryName+0x19 (FPO: [Non-Fpo])
    23.         ed688c5c 80553d84 nt!ObQueryNameString+0xa5 (FPO: [Non-Fpo])
    24.         ed688d48 804d4e91 nt!NtQueryObject+0x229 (FPO: [Non-Fpo])
    25.         ed688d48 7ffe0304 nt!KiSystemService+0xc4 (FPO: [0,0] TrapFrame @ ed688d64)
    26.         0130ffec 00000000 SharedUserData!SystemCallStub+0x4 (FPO: [0,0,0])




    Глянул Kernel Debugger'ом. Все потоки ждут на событии (каждый на своём). Событие создает IopQueryXxxInformation, и шлет драйверу обслуживающему файл IRP_MJ_QUERY_INFORMATION. Потом начинает ждать. Вот тут они и висят. Что с этим делать, я не знаю.
     
  13. Viewsight

    Viewsight New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2004
    Сообщения:
    11
    Всё я решил эту проблему...



    Прежде чем обращаться к объекту файл я запрашиваю атриббуты его при создании и если &FILE_SEQUENTIAL_ONLY

    Хрен к нему мы обратимся....



    Все зависоны прошли.....
     
  14. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Ну, зер гут. Запомним.
     
  15. alik

    alik New Member

    Публикаций:
    0
    Регистрация:
    1 июн 2005
    Сообщения:
    2
    Адрес:
    Afghanistan




    а как это сделать?
     
  16. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Открыть "Native API Reference" by Gary Nebbett и в поиске набрать: FILE_SEQUENTIAL_ONLY
     
  17. alik

    alik New Member

    Публикаций:
    0
    Регистрация:
    1 июн 2005
    Сообщения:
    2
    Адрес:
    Afghanistan
    если бы всё так просто было...

    NtQueryInformationFile(..., FileModeInformation) для пайпа тоже приводит к дидлоку
     
  18. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Очень плохо :dntknw: Придется надеятся на объяснения автора метода, ибо я практически его не применял.