Системный вызов в Android NDK


person Phillip    schedule 02.06.2018    source источник
comment
Можете ли вы опубликовать минимально воспроизводимый пример этого? Код и как именно вы его скомпилировали? Не очевидно, как это может повредить стек, если только вы не создали переполнение буфера, передав неверный указатель на read.   -  person Peter Cordes    schedule 02.06.2018
comment
@PeterCordes Привет, Питер, я ждал от тебя ответов в другой ветке (чате), я написал там подробности. Я собираюсь подготовить минимальный пример сегодня.   -  person Phillip    schedule 02.06.2018
comment
У меня нет бесконечного времени (к сожалению). Если я доберусь до этого, я добавлю подробности к своему ответу на ваш другой вопрос, а не где-то в чате. Если бы в вашем другом вопросе в первую очередь говорилось о С++, я бы не дал вам ответ только на C.   -  person Peter Cordes    schedule 02.06.2018
comment
@PeterCordes Я знаю, извини. Но мне очень нужна небольшая помощь. Минимальный код: godbolt.org/g/KFpQyf, но он дает некоторые ошибки регистрации. Я пробовал это в Android NDK для arm_64, и он компилируется   -  person Phillip    schedule 02.06.2018
comment
Кто-нибудь может помочь?   -  person Phillip    schedule 04.06.2018
comment
В Godbolt вы пытались скомпилировать код AArch64 (с такими регистрами, как x0) с помощью компилятора ARM32. Он отлично компилируется для AArch64-gcc: godbolt.org/g/SgoqoE. ARM32 использует r0..r14 (r15 — ПК, счетчик программ).   -  person Peter Cordes    schedule 04.06.2018
comment
Спасибо @PeterCordes, я могу успешно скомпилировать код для моей цели, но проблема в том, что он падает после выполнения, как я уже упоминал в основном вопросе. Я использую неправильные параметры?   -  person Phillip    schedule 04.06.2018


Ответы (1)


У вас есть по крайней мере одна ошибка в коде ссылки Godbolt, которую вы разместили. Эти операторы приводят к переполнению буфера (окружающий код и условия if() удалены).

char buffer[2048];

    length = syscall_read(fd, buffer, sizeof(buffer));

        buffer[length] = 0;

buffer[length] = 0; обращается за пределами массива, если sys_read возвращает 2048. Как сказано на странице руководства, read() пытается прочитать до count байт, а не count-1. Это может объяснить повреждение стека, если массив был выделен прямо под чем-то важным.

Вы должны оставить место для терминатора 0, если вы хотите использовать его как строку неявной длины C вместо буфера явной длины + размер с write или memcpy или что-то еще. Помните, что данные файла могут содержать 0 байт.

Как обычно, используйте отладчик и убедитесь, что ваш код работает с обычными системными вызовами, а также со встроенными оболочками.

person Peter Cordes    schedule 04.06.2018
comment
Спасибо, я изменил третий параметр syscall_read на sizeof(buffer) - 1, и проблема остается. На самом деле длина файла меньше 1024, даже близко не 2048. У меня все еще есть повреждение стека. - person Phillip; 04.06.2018
comment
@Phillip: Вы strace сделали это, чтобы убедиться, что системные вызовы выполняются успешно? Или прокомментируйте материал до тех пор, пока проблема не исчезнет, ​​а затем посмотрите, какая память используется кодом для этой строки? (Предполагая, что проблема все еще возникает с отключенной оптимизацией, поэтому каждая строка компилируется в отдельный блок asm). И проблема все еще возникает, если вы вызываете read() обычно вместо вашей встроенной версии? У меня нет среды разработки Android, чтобы протестировать это, даже если бы я хотел. В вашем вопросе даже нет вашего кода, не говоря уже о какой-либо информации от отладчика, поэтому IDK, если кто-то может вам помочь. - person Peter Cordes; 04.06.2018
comment
Спасибо, я переименовал типы и добавил faccessat перед openat и он заработал нормально :) - person Phillip; 04.06.2018
comment
@Phillip: Добавление faccessat, вероятно, просто совпадение, поскольку разные генераторы кода скрывают любую вашу ошибку. Изменение типов может привести к различиям, если они были неправильными, в противном случае простое использование большего или меньшего пространства в стеке, вероятно, снова скрывает ошибку. - person Peter Cordes; 04.06.2018
comment
Я тщательно протестирую его, и если я получу подобную ошибку, я добавлю сюда результат. На данный момент это работает, я пробовал getpid exit и open read write close call 100 раз, и все в порядке. - person Phillip; 04.06.2018