2013-01-11 5 views
0

저는 C에서 상당히 익숙하며 EV_KEY 이벤트를 처리하는 모든 이벤트 핸들러를 열고, 파일 기술자 목록을 제공하는 유틸리티를 작성하려고합니다. 다시 열림). 을 모두 수행하는 함수는 파일 설명자를 반복하려고 할 때 제대로 작동하려면으로 나타나고, 스택 오류가 발생합니다. gcc의 -Wall 플래그로 각 C 파일을 컴파일하여 문제의 원인을 찾을 수 있었지만 문제가되지 않았습니다. 여기에 내 코드입니다 : 여기int 포인터를 반복 할 때 스매쉬 된 스택

int *get_key_handlers() { 

    int *fds; 
    int fd; 
    int num_handlers = 0; 
    struct dirent *dp; 
    DIR *dir; 
    char full_path[100]; 
    char *base_path = "/dev/input/"; 

    printf("Creating file descriptor array\n"); 
    fds = malloc(sizeof(int*)*32); // not currently going to bother 
            // with more than 32 handlers 

    printf("Opening event handler directory\n"); 
    if (!(dir = opendir(base_path))) { 
     return 1; 
    } 

    printf("Beginning reading through directory\n"); 
    while ((dp = readdir(dir))) { 

     if (dp->d_name && !strncmp(dp->d_name, "event", 5)) { 

      // cat the base path and device name, store in full_path 
      snprintf(full_path, sizeof(full_path), "%s%s", base_path, dp->d_name); 
      printf("Found handler at %s\n", full_path); 
      fd = open(full_path, O_RDONLY); 

      printf("Detecting handler features...\n"); 
      unsigned char results[EV_MAX/8+1]; 
      memset(results, 0, sizeof(results)); 
      ioctl(fd, EVIOCGBIT(EV_KEY, EV_MAX), results); 
      printf("Features determined\n"); 
      printf("EV_KEY: %d\n", EV_KEY); 
      if (test_bit(*results, EV_KEY)) { 
       printf("EV_KEY feature detected on %s\n", full_path); 
       fds[num_handlers] = fd; 
       num_handlers++; 
      } else { 
       printf("EV_KEY feature NOT detected on %s\n", full_path); 
       close(fd); 
      } 
      printf("Done with handler at %s\n", full_path); 
     } 
    } 
    printf("Finished creating handler list\n"); 

    fds = realloc(fds, sizeof(int*) * num_handlers); 
    printf("Handler list re-sized\n"); 
    return fds; 
} 

가 get_key_handlers를 호출하는 코드입니다() 함수 : 모든

int main() { 
    int *fds = get_key_handlers(); 
    int i = 0; 
    for (i = 0; i < (sizeof(fds)/sizeof(int*)); i++) { 
     printf("Next file descriptor: %d\n", *(fds + (i * sizeof(int*)))); 
    } 

    free(fds); 
    return 0; 
} 

마지막으로, 여기에 내가 링크를 컴파일하고 실행하는거야 명령은 실행과 함께하다 프로그램의 출력 :

[email protected]:~/Documents/Programming/C/clogger$ gcc -c -Wall thinput.c 
thinput.c: In function ‘get_key_handlers’: 
thinput.c:21:9: warning: return makes pointer from integer without a cast [enabled by default] 
[email protected]:~/Documents/Programming/C/clogger$ gcc -c -Wall thinputtest.c 
[email protected]:~/Documents/Programming/C/clogger$ gcc thinput.o thinputtest.o -o thinputtest 
[email protected]:~/Documents/Programming/C/clogger$ sudo ./thinputtest 
Creating file descriptor array 
Opening event handler directory 
Beginning reading through directory 
Found handler at /dev/input/event15 
Detecting handler features... 
Features determined 
EV_KEY: 1 
EV_KEY feature NOT detected on /dev/input/event15 
Done with handler at /dev/input/event15 
Found handler at /dev/input/event14 
Detecting handler features... 
Features determined 
EV_KEY: 1 
EV_KEY feature detected on /dev/input/event3 
Done with handler at /dev/input/event3 
Found handler at /dev/input/event2 
Detecting handler features... 
Features determined 
EV_KEY: 1 
EV_KEY feature NOT detected on /dev/input/event1 
Done with handler at /dev/input/event1 
Found handler at /dev/input/event0 
Detecting handler features... 
Features determined 
EV_KEY: 1 
EV_KEY feature NOT detected on /dev/input/event0 
Done with handler at /dev/input/event0 
Finished creating handler list 
Handler list re-sized 
*** stack smashing detected ***: ./thinputtest terminated 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f0ef8658807] 
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x0)[0x7f0ef86587d0] 
./thinputtest[0x400ac7] 
======= Memory map: ======== 
00400000-00401000 r-xp 00000000 08:02 7215828       /home/tim/Documents/Programming/C/clogger/thinputtest 
00601000-00602000 r--p 00001000 08:02 7215828       /home/tim/Documents/Programming/C/clogger/thinputtest 
00602000-00603000 rw-p 00002000 08:02 7215828       /home/tim/Documents/Programming/C/clogger/thinputtest 
01b88000-01ba9000 rw-p 00000000 00:00 0         [heap] 
7f0ef8338000-7f0ef834d000 r-xp 00000000 08:02 5247337     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f0ef834d000-7f0ef854c000 ---p 00015000 08:02 5247337     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f0ef854c000-7f0ef854d000 r--p 00014000 08:02 5247337     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f0ef854d000-7f0ef854e000 rw-p 00015000 08:02 5247337     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f0ef854e000-7f0ef8703000 r-xp 00000000 08:02 5247958     /lib/x86_64-linux-gnu/libc-2.15.so 
7f0ef8703000-7f0ef8902000 ---p 001b5000 08:02 5247958     /lib/x86_64-linux-gnu/libc-2.15.so 
7f0ef8902000-7f0ef8906000 r--p 001b4000 08:02 5247958     /lib/x86_64-linux-gnu/libc-2.15.so 
7f0ef8906000-7f0ef8908000 rw-p 001b8000 08:02 5247958     /lib/x86_64-linux-gnu/libc-2.15.so 
7f0ef8908000-7f0ef890d000 rw-p 00000000 00:00 0 
7f0ef890d000-7f0ef892f000 r-xp 00000000 08:02 5255999     /lib/x86_64-linux-gnu/ld-2.15.so 
7f0ef8b08000-7f0ef8b0b000 rw-p 00000000 00:00 0 
7f0ef8b2b000-7f0ef8b2f000 rw-p 00000000 00:00 0 
7f0ef8b2f000-7f0ef8b30000 r--p 00022000 08:02 5255999     /lib/x86_64-linux-gnu/ld-2.15.so 
7f0ef8b30000-7f0ef8b32000 rw-p 00023000 08:02 5255999     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffbd9b4000-7fffbd9d5000 rw-p 00000000 00:00 0       [stack] 
7fffbd9ff000-7fffbda00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

이 문제를 해결하는 데 시간을 할애 해 주셔서 대단히 감사합니다. 나는 어떤 조언이나 비평을 내 방식대로 보내 주셔서 감사합니다!

ioctl(fd, EVIOCGBIT(EV_KEY, EV_MAX), results); 

변화 라인 : 당신은 간접적으로 그것을 동안 채우기 위해 EV_MAX 바이트를 가지고 EVIOCGBIT을 말함으로써 외부 results '경계 작성

ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(results)), results); 

+3

야해? 또한 AFAIK 함수의'strncmp' 함수의 반환 값은 요구 사항에 따라'0' 또는'1' 또는'-1'과 비교되어야합니다. – Recker

+0

strncmp의 경우 0 인 경우 그것은 일치한다는 것을 의미하므로 계속 진행하기를 원합니다. ! strcmp()는 문자열이 일치하면 "true"를 반환합니다. – Haz

+0

또한, malloc 된 메모리에 대한 포인터가 있으면 메모리 덩어리가 얼마나 큰지 알 수 없습니까? 나는 malloc이 할당 된 메모리의 크기를 포함하는 추가 정보를 그 메모리에 추가했다고 생각했다. – Haz

답변

1

ioctl 잘못된 크기가 EV_MAX ÷ 8 만 있으므로 스택이 휴지통으로 처리됩니다. 스택 스매싱 감지 기능이 작동하는 방식으로 인해 return 번만 감지 할 수 있습니다.

당신이 확신을 얻으려면, drivers/input/evdev.c의 코멘트를 살펴 보라는 말한다 :`는 sizeof (int)를 * 32` 수

/* 
* Work around bugs in userspace programs that like to do 
* EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' 
* should be in bytes, not in bits. 
*/ 
+0

나는 이것이 문제라고 생각하지 않는다. 런타임 출력을 살펴보면 스택 스매싱이 감지 될 때까지 파일 설명자를 반환했습니다. – Haz

+0

@Haz 나는 이것이 문제라고 확신한다. 나는 당신에게 세부 사항을 줄 대답을 편집했다. 실제로 해결책을 시도해 보셨습니까? – kmkaplan

+0

와우, 그 정보 주셔서 감사합니다. 오늘 밤 집에 올 때 그것을 시험해보고 해결한다면 답을 받아 들일 것입니다. – Haz