Linux, FreeBSD, OpenBSD autodetect code

Тема в разделе "WASM.UNIX", создана пользователем Quantum, 16 сен 2006.

  1. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Откопал в одном туторе, что по значению регистра gs можно определить ось. Написал тестовый код для Gcc:
    Код (Text):
    1. enum OS_TYPE{
    2.     OS_LINUX,
    3.     OS_FREEBSD,
    4.     OS_OPENBSD,
    5.     OS_UNKNOWN
    6. };
    7.  
    8. int getOS(){
    9. int ret_val;
    10.     asm(    "xorl %%eax,%%eax\n\t"
    11.         "movw %%gs,%%ax"
    12.         : "=a" (ret_val)
    13.     );
    14.     switch(ret_val){
    15.         case 0:    return OS_LINUX;
    16.         case 0x2F: return OS_FREEBSD;
    17.         case 0x1F: return OS_OPENBSD;
    18.     }
    19.     return OS_UNKNOWN;
    20. }
    Попробовал пока только во FreeBSD 5.3 и Linux DSL 3.0.1. Работает. Прокомментируйте, пожалуйста, перспективность подобного кода. На основании getOS() я потом подгружаю таблицу кодов системных вызовов для каждой оси и работаю без сишной либы. К примеру, системный вызов rename (переименовать файл) в Linux имеет код 38, а в BSD - 128. Поэтому приходится или поддерживать несколько разных версий программы, или "детектить" ось в рантайме вышеприведенным способом.

    Если можете проверить работоспособность getOS() на других дистрах, отпишитесь. Спасибо.
     
  2. Broken Sword

    Broken Sword Robert

    Публикаций:
    0
    Регистрация:
    30 авг 2002
    Сообщения:
    433
  3. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    по типу раздела не стоит. линух, например, вообще не смотрит на это поле. И у меня до сих пор, согласно fdisk -l, присутствуют ntfs и fat разделы. Хотя ничего кроме ext3 уже давно нету.
     
  4. razor

    razor Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    40
    Код (Text):
    1. $ cat test_os.c
    2.  
    3. #include <stdio.h>
    4.  
    5. int main(){
    6.     int ret_val;
    7.     asm(    "xorl %%eax,%%eax\n\t"
    8.         "movw %%gs,%%ax"
    9.         : "=a" (ret_val)
    10.     );
    11.     switch(ret_val){
    12.         case 0:         printf("OS_LINUX\n");   break;
    13.         case 0x2F:      printf("OS_FREEBSD\n");break;
    14.         case 0x1F:      printf("OS_OPENBSD\n");break;
    15.                 default:        printf("OS_UNKNOWN, gs = 0x%X\n", ret_val);
    16.     }
    17.     return 0;
    18. }
    19. $ uname -rsm
    20. OpenBSD 3.9 i386
    21. $ ./test_os
    22. OS_UNKNOWN, gs = 0x27
    23.  
    24. $ uname -rsm
    25. FreeBSD 6.1-RELEASE i386
    26. $ ./test_os
    27. OS_UNKNOWN, gs = 0x1B
     
  5. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    razor
    Спасибо!

    Возможно, у них и коды системных вызовов изменились. Не могли бы Вы приаттачить (или запостить ссылку) на syscalls.master для этих 2х?

    Кстати, может, стартовый код изменяет gs? Теоретически, надёжнее тестить без стандартных либ, т.е. так:
    Код (Text):
    1. // os_detect.c:
    2. void _start(char* argv0){
    3.     // тут вызываем getOS()
    4.     _exit(0);
    5. }
    И собираем:
    gcc -Wall -O2 -s -nostartfiles -nodefaultlibs -nostdlib -static os_detect.c -o os_detect
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Broken Sword
    Этот вариант ещё менее надёжен, чем тот, что я пытаюсь использовать. Всё-таки тип раздела не должен зависеть от типа оси и, тем более, от конкретной версии. Зато стартовое значение регистров в одной и тойже версии любого конкретного дистрибутива *никса меняться не должно, imho.

    ЗЫ: В Mandrake 10 код работает.
     
  7. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Я тут побыстрому переписал на асм, надеюсь не ошибся нигде
    на SuSe10 код показывает ->LINUX :)
    Код (Text):
    1. format ELF executable
    2. entry start
    3.  
    4. macro hex2ascii
    5. {
    6.    cmp  al,10
    7.    sbb  al,69h
    8.    das
    9. }
    10.  
    11. section readable executable
    12.  
    13. start:
    14.  
    15. xor eax, eax
    16. mov ax, gs
    17.  
    18. test eax, eax
    19. mov ecx, szOS_LINUX
    20. jz @F
    21.  
    22. cmp eax, 0000002Fh
    23. mov ecx, szOS_FREEBSD
    24. je @F
    25.  
    26. cmp eax, 0000001Fh
    27. mov ecx, szOS_OPENBSD
    28. je @F
    29.  
    30. mov ecx,szOS_UNKNOWN
    31.  
    32. @@:
    33. mov [temp_reg],ax
    34. call convert_proc
    35. mov WORD [ecx+3], ax
    36. mov WORD [ecx+5], dx
    37.  
    38. mov eax,4
    39. mov ebx,1
    40. mov edx,msg_size
    41. int 0x80
    42.  
    43. mov eax,1
    44. xor ebx,ebx
    45. int 0x80
    46.  
    47. convert_proc:
    48.   mov al, BYTE [temp_reg]
    49.   call al2ascii
    50.   mov dx, ax
    51.   mov al, BYTE [temp_reg+1]
    52.   call al2ascii
    53.   ret
    54.  
    55. al2ascii:
    56.   aam 16
    57.   hex2ascii
    58.   xchg al, ah
    59.   hex2ascii
    60.   ret
    61.  
    62. section readable writeable
    63.  
    64. szOS_LINUX   db 'gs=0000->_LINUX_',0xA
    65. szOS_FREEBSD db 'gs=0000->FREEBSD',0xA
    66. szOS_OPENBSD db 'gs=0000->OPENBSD',0xA
    67. szOS_UNKNOWN db 'gs=0000->UNKNOWN',0xA
    68. msg_size = $ - szOS_UNKNOWN
    69. temp_reg  dw  0
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Asterix
    Замечательно.

    Knoppix 4.0.2 тоже прошёл тест.
     
  9. Broken Sword

    Broken Sword Robert

    Публикаций:
    0
    Регистрация:
    30 авг 2002
    Сообщения:
    433
    Просто именно для трех типов выше можно по ID раздела однозначно сказать что за ось. OpenBSD - всегда A6, FreeBSD - A5. С линухом не уверен. А инициализация gs может измениться в любом релизе.
     
  10. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Broken Sword
    Выяснилось, что коды сисколов могут меняться в версиях одной и той же оси. Поэтому пока что вариант с gs набирает больше очков.

    Будет повод выпустить новую версию детектора оси ;)
     
  11. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    Немного изменил код под BSD вызовы
    Код (Text):
    1. #
    2. # fasm os_detect.asm os_detect.o
    3. # ld --strip-all -o os_detect os_detect.o
    4. #
    5.               format ELF
    6.               public _start
    7.  
    8. macro hex2ascii
    9. {
    10.     cmp  al,10
    11.     sbb  al,69h
    12.     das
    13. }
    14.  
    15. section '.text' executable align 16
    16.  
    17. _start:
    18.               xor     eax,eax
    19.           mov     ax,gs
    20.           test    eax,eax
    21.           mov     ecx, szOS_LINUX
    22.           jz      @F
    23.          
    24.           cmp     eax,0000002Fh
    25.           mov     ecx,szOS_FREEBSD
    26.           je      @F
    27.  
    28.           cmp     eax,0000001Fh
    29.           mov     ecx,szOS_OPENBSD
    30.           je      @F
    31.  
    32.           mov     ecx,szOS_UNKNOWN
    33.  
    34.      @@:
    35.           mov     [temp_reg],ax
    36.           call    convert_proc
    37.           mov     WORD [ecx+3], ax
    38.           mov     WORD [ecx+5], dx
    39.  
    40.               push    msg_size
    41.               push    ecx
    42.               push    1
    43.               mov     eax,4
    44.               push    eax
    45.               int     80h
    46.               add     esp,4*4
    47.              
    48.               xor     eax,eax
    49.               push    eax
    50.               inc     eax
    51.               int     0x80
    52.  
    53. convert_proc:
    54.               mov     al,BYTE [temp_reg]
    55.               call    al2ascii
    56.               mov     dx,ax
    57.               mov     al,BYTE [temp_reg+1]
    58.               call    al2ascii
    59.               ret
    60.      
    61. al2ascii:
    62.               aam     16
    63.               hex2ascii
    64.               xchg    al,ah
    65.               hex2ascii
    66.               ret
    67.    
    68. section '.data' writeable align 4
    69.  
    70. szOS_LINUX   db 'gs=0000->_LINUX_',0xA
    71. szOS_FREEBSD db 'gs=0000->FREEBSD',0xA
    72. szOS_OPENBSD db 'gs=0000->OPENBSD',0xA
    73. szOS_UNKNOWN db 'gs=0000->UNKNOWN',0xA
    74. msg_size = $ - szOS_UNKNOWN
    75. temp_reg  dw  0
    76.  
    77. % uname -rms                
    78. FreeBSD 5.5-STABLE i386
    79. % ./os_detect
    80. gs=002F->FREEBSD
     
  12. Bert

    Bert New Member

    Публикаций:
    0
    Регистрация:
    11 май 2005
    Сообщения:
    20
    Адрес:
    Russia
    Взял код у razor.

    > uname -rsm
    Linux 2.6.18-rc3 i686
    > ./test_os
    OS_UNKNOWN, gs = 0x33

    Дистрибутив - Gentoo.
     
  13. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    KiNDeR
    Bert
    Спасибо!

    Т.к. Линуксов в природе больше, думаю, что имеет смысл по дефолту OS_UNKNOWN приравнять к OS_LINUX.

    All
    Где бы найти таблицы с кодами сисколов под каждую версию этих осей? Отдельные экземпляры я нашёл только в самих дистрибутивах, которые у меня есть. Неужели нет централизованного хранилища? Только не надо посылать меня сюда - сплошные неточности.
     
  14. shurik

    shurik Александр

    Публикаций:
    0
    Регистрация:
    27 авг 2006
    Сообщения:
    52
    Адрес:
    Украина
    Думаю что это будет все-таки немного не правильно.
    Использовал код KiNDeR'а на FreeBSD 6.0-RELEASE i386
    Результат:
    gs=003B->UNKNOWN
     
  15. kyprizel

    kyprizel New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2003
    Сообщения:
    232
    Адрес:
    TSK
    мои результаты для FreeBSD:

    4.11-RELEASE
    OS_FREEBSD

    5.4-RELEASE
    OS_UNKNOWN, gs = 0x8F

    5.4-RELEASE-p11
    OS_UNKNOWN, gs = 0x8F

    5.4-RELEASE-p15
    OS_UNKNOWN, gs = 0x8F

    6.0-RELEASE-p7
    OS_UNKNOWN, gs = 0x1B

    6.1-STABLE
    OS_UNKNOWN, gs = 0x1B
     
  16. kyprizel

    kyprizel New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2003
    Сообщения:
    232
    Адрес:
    TSK
    линукс я весь извел, но вот то что удалось получить:

    Slackware, Linux 2.4.31
    OS_LINUX

    Slackware, Linux 2.6.17.11
    OS_UNKNOWN, gs = 0x33
     
  17. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    В аттаче небольшой итог проведенного всеми участниками данного топика тестирования. Экзешник собирается через make с помощью gcc. Никаких зависимостей не содержит. Должен без проблем запускаться под любыми *никсами. Первым делом выводит текущее значение GS и тип/версию оси по таблице. Потом пытается создать файл 1.txt и переименовать его в 2.txt. Понятно, что для этого проще заюзать шелл, но вместо syscall_rename в реальном приложении может понадобиться другой "стандартный" системный вызов.
     
  18. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    osdetect.c - строка 47:
    OS_FREEBSD_6_x заменить на OS_FREEBSD_6_X :))
     
  19. Bert

    Bert New Member

    Публикаций:
    0
    Регистрация:
    11 май 2005
    Сообщения:
    20
    Адрес:
    Russia
    Для линукса таблицу сисколов надо смотреть в исходниках ядра. Называется sys_call_table. Смотреть, например, здесь:
    arch/i386/syscall_table.S
    arch/ia64/entry.S
    include/asm-x86_64/unistd.h

    Согласно Documentation/ABI/stable/syscalls, номера меняться вряд ли будут, разве что добавляться.

    Таблица сисколов не имеет никакой связи с дистрибутивами, она - часть самого ядра. Поэтому централизованное хранилище - это любой исходник ядра, скачаный, например, с www.kernel.org :)
     
  20. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Bert
    Таблица для Linux 2.4 у меня есть, т.к. есть дистрибутивы с этим ядром. А других нет, т.к. нет дистрибутивов. Поэтому возник вопрос - где скачать (не качая целый дистр)?

    В Линуксе изменений не замечал, кроме добавлений, конечно. Зато в FreeBSD и OpenBSD изменения есть, если верить тем немногим syscalls.master, которые удалось найти для разных версий.

    Кто бы спорил.

    Может быть, я просто не умею искать на той свалке, но таблицы для *никсов по версиям я вторую неделю не могу найти в сети. Нашёл кое-что для отдельных версий, но далеко не всех.

    KiNDeR
    Пришлось немного изменить исходник, чтоб добавить информацию из последних сообщений kyprizel. Поэтому вышла ошибочка.