LINUX.ORG.RU

Ответ на: комментарий от mv

Нужная информация там бесспорно есть, но парсить этот файл на каждый раз, как нужно узнать права доступа к памяти - это слишком медленно. Есть другие варианты? Вот для установки прав доступа есть mprotect(), а на получение прав доступа я системного вызова не нашел.

ccoder
() автор топика
Ответ на: комментарий от ccoder

> Есть другие варианты? Вот для установки прав доступа есть mprotect(), а на получение прав доступа я системного вызова не нашел.

И как бы подобный вызов работал, если ему передать диапазон, лежащий за границей одного vma?

mv ★★★★★
()
Ответ на: комментарий от ratatosk

> mprotect, вроде, EINVAL вернет при попытке установить права на отсутствующую страницу.

А если она не отсуствуе - изменит ей права. Нихрена себе побочный эффект проверки на читаемость :)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> А в чем проблема поставить обработчик сигнала?

Этот код будет в библиотеке. Если ставить обработчик, нужно потом его восстанавливать - а это влечет за собой применение мер для нормальной работы в многопоточном окружении. Не хотелось бы такое городить.

ccoder
() автор топика
Ответ на: комментарий от mv

>> Есть другие варианты? Вот для установки прав доступа есть mprotect(), а на получение прав доступа я системного вызова не нашел.

>И как бы подобный вызов работал, если ему передать диапазон, лежащий за границей одного vma?

В идеале, мне нужна такая функция:

bool is_pointer_readable(void *p);

Если можно читать - возвращает true, если нет - false.

ccoder
() автор топика
Ответ на: комментарий от tailgunner

мда, да и вообще, мпротект тоже SIGSEGV присылает...

ratatosk
()
Ответ на: комментарий от tailgunner

> Тогда я бы прикола ради попробовал ptrace на самом процессе :)

Самого себя трассировать нельзя.

mv ★★★★★
()
Ответ на: комментарий от ccoder

А в винапи такая функция была, но после win9x отпилили, ибо мудачество. Там, кстати(в оффтопе), такое через SEH рекомендуют проверять, по крайней мере я такую реализацию видел.

nikolayd
()
Ответ на: комментарий от nikolayd

> http://msdn.microsoft.com/en-us/library/aa366713(VS.85).aspx вот ниже по странице статья с пояснениями.

Вот что пишут:

In a preemptive multitasking environment, it is possible for some other thread to change the process's access to the memory being tested.

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

ccoder
() автор топика
Ответ на: комментарий от ccoder

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

Вообще говоря, даже с обработчиком засада - между проверкой памяти и ее использованием проходит некоторое время, и за него зашита може измениться. Классическая гонка.

tailgunner ★★★★★
()
Ответ на: комментарий от legolegs

> В порядке бреда: форкнуться и прочитать в потомке :)

Дорого, но вроде бы сработает как надо.

const86 ★★★★★
()
Ответ на: комментарий от ccoder

>В идеале, мне нужна такая функция:
>
>bool is_pointer_readable(void *p); 

void* не может быть разыменован.

Можно попробовать что-нибудь вроде (каждый раз открывать файл, выделять память и проч., естественно, не обязательно):
int is_read_ptr(void *ptr, int size)
{
        int fd, rc;
        char *buf = (char *)malloc(size);

        fd = open("/proc/self/mem", O_RDONLY);
        rc = pread(fd, buf, size, (unsigned long)ptr);
        close(fd);
        free(buf);
        return rc == size;
}

Murr ★★
()
Ответ на: комментарий от tailgunner

> Вообще говоря, даже с обработчиком засада - между проверкой памяти и ее использованием проходит некоторое время, и за него зашита може измениться. Классическая гонка.

Я это и имею ввиду - ставить обработчик и пытаться использовать память. При неудаче будет сигнал, при удаче - дело уже сделано.

ccoder
() автор топика
Ответ на: комментарий от Davidov

> А зачем это нужно?

>Просто интересно.

Для грязного хака. Это нужно, чтобы этот хак не рушил процессы. Подробно описывать не буду, это долго и никому не интересно.

ccoder
() автор топика
Ответ на: комментарий от Murr

> Можно попробовать что-нибудь вроде (каждый раз открывать файл, выделять память и проч., естественно, не обязательно):

Интересно, большое спасибо.

ccoder
() автор топика
Ответ на: комментарий от ccoder

Пожалуйста.

Даже вроде работает на первый взгляд:

/tmp # cat zzz.c 
#define _LARGEFILE_SOURCE  
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#define _XOPEN_SOURCE 500   
#include <unistd.h>         
#include <fcntl.h>          
#include <stdlib.h>         
#include <assert.h>         
#include <stdio.h>          

int is_read_ptr(void *ptr, int size)
{                                   
        int fd, rc;                 
        char *buf = (char *)malloc(size);

        fd = open("/proc/self/mem", O_RDONLY);
        rc = pread(fd, buf, size, (unsigned long)ptr);
        close(fd);                                    
        free(buf);                                    
        return rc == size;                            
}                                                     

int main(int argc, char *argv[])
{                               
        unsigned long last = 0, i;
        int rc;
        char buf[10000];

        for (i=0; i<=0xbfffffffUL; i += 4096) {
                rc = is_read_ptr(i, 1);
                if (last == 0 && rc)
                        last = i;
                if (rc == 0 && last != 0) {
                        printf("%p-%p\n", last, i);
                        last = 0;
                }
        }

        rc = open("/proc/self/maps", O_RDONLY);
        i = read(rc, buf, 10000);
        write(0, buf, i);
        close(rc);

        return 0;
}
/tmp # ./a.out
0x8048000-0x806c000
0xb7da5000-0xb7f02000
0xb7f42000-0xb7f64000
0xbf163000-0xbf963000
08048000-08049000 r-xp 00000000 08:02 126542     /tmp/a.out
08049000-0804a000 r--p 00000000 08:02 126542     /tmp/a.out
0804a000-0804b000 rw-p 00001000 08:02 126542     /tmp/a.out
0804b000-0806c000 rw-p 0804b000 00:00 0          [heap]
b7da5000-b7da6000 rw-p b7da5000 00:00 0
b7da6000-b7efb000 r-xp 00000000 08:02 250400     /lib/libc-2.9.so
b7efb000-b7efc000 ---p 00155000 08:02 250400     /lib/libc-2.9.so
b7efc000-b7efe000 r--p 00155000 08:02 250400     /lib/libc-2.9.so
b7efe000-b7eff000 rw-p 00157000 08:02 250400     /lib/libc-2.9.so
b7eff000-b7f02000 rw-p b7eff000 00:00 0
b7f42000-b7f44000 rw-p b7f42000 00:00 0
b7f44000-b7f62000 r-xp 00000000 08:02 25241      /lib/ld-2.9.so
b7f62000-b7f63000 r--p 0001d000 08:02 25241      /lib/ld-2.9.so
b7f63000-b7f64000 rw-p 0001e000 08:02 25241      /lib/ld-2.9.so
bf163000-bf963000 rw-p bf800000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]

Murr ★★
()

Самый переносимый метод -- попросить ядро почитать из этой памяти. Открываешь /dev/null, вызываешь системный вызов write() в него, указав в качестве адреса буфера интересующий адрес, в качестве длины -- интересующую длину. Если этого участка памяти нет в твоём адресном пространстве, системный вызов вернёт ошибку. Не скажу какую, read(2) нет под рукой. Точно также можно проверять "писабельность", открывая /dev/zero и вызывая read() из него в интересующий участок памяти. Работать будет на любом UNIX-е.

iliyap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.