.\" -*- coding: UTF-8 -*- .\" Copyright (C) 2007 Michael Kerrisk .\" and Copyright (C) 1995 Michael Shields . .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\" Modified 1996-10-22 by Eric S. Raymond .\" Modified 1997-05-31 by Andries Brouwer .\" Modified 2003-08-24 by Andries Brouwer .\" Modified 2004-08-16 by Andi Kleen .\" 2007-06-02, mtk: Fairly substantial rewrites and additions, and .\" a much improved example program. .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH mprotect 2 "5 февраля 2023 г." "Linux man\-pages 6.03" .SH ИМЯ mprotect, pkey_mprotect \- контролирует доступ к области памяти .SH LIBRARY Standard C library (\fIlibc\fP, \fI\-lc\fP) .SH СИНТАКСИС .nf \fB#include \fP .PP \fBint mprotect(void \fP\fIaddr\fP\fB[.\fP\fIlen\fP\fB], size_t \fP\fIlen\fP\fB, int \fP\fIprot\fP\fB);\fP .PP \fB#define _GNU_SOURCE\fP /* смотрите feature_test_macros(7) */ \fB#include \fP .PP \fBint pkey_mprotect(void \fP\fIaddr\fP\fB[.\fP\fIlen\fP\fB], size_t \fP\fIlen\fP\fB, int \fP\fIprot\fP\fB, int \fP\fIpkey\fP\fB);\fP .fi .SH ОПИСАНИЕ Вызов \fBmprotect\fP() изменяет параметры доступа страниц памяти вызывающего процесса, которые содержатся, даже частично, в адресном диапазоне [\fIaddr\fP,\ \fIaddr\fP+\fIlen\fP\-1]. Значение \fIaddr\fP должно быть выровнено на границу страницы. .PP Если вызывающий процесс нарушает защиту доступа к памяти, то ядро посылает процессу сигнал \fBSIGSEGV\fP. .PP Значение \fIprot\fP представляет собой комбинацию следующих флагов доступа: \fBPROT_NONE\fP или побитово сложенные другие значения из следующего списка: .TP \fBPROT_NONE\fP Доступ к памяти запрещён. .TP \fBPROT_READ\fP Память можно читать. .TP \fBPROT_WRITE\fP Память можно изменять. .TP \fBPROT_EXEC\fP Память можно выполнять. .TP \fBPROT_SEM\fP (начиная с Linux 2.5.7) Память можно использовать для атомарных операций. Этот флаг появился как часть реализации \fBfutex\fP(2) (для гарантии способности выполнять атомарные операции, требуемые таким командам как \fBFUTEX_WAIT\fP), но пока не используется ни в одной архитектуре. .TP \fBPROT_SAO\fP (начиная с Linux 2.6.26) .\" commit aba46c5027cb59d98052231b36efcbbde9c77a1d .\" commit ef3d3246a0d06be622867d21af25f997aeeb105f Память должна иметь строгий порядок доступа. Это свойство есть только в архитектуре PowerPC (в спецификации архитектуры версии 2.06 добавлено свойство ЦП SAO и оно доступно, например, на POWER 7 или PowerPC A2). .PP Также (начиная с Linux 2.6.0), \fIprot\fP может содержать один из следующих установленных флагов: .TP .\" mm/mmap.c: .\" vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | .\" mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; .\" And calc_vm_flag_bits converts only GROWSDOWN/DENYWRITE/LOCKED. \fBPROT_GROWSUP\fP .\" The VMA is one that was marked with VM_GROWSUP by the kernel .\" when the stack was created. Note that (unlike VM_GROWSDOWN), .\" there is no mmap() flag (analogous to MAP_GROWSDOWN) for .\" creating a VMA that is marked VM_GROWSUP. Apply the protection mode up to the end of a mapping that grows upwards. (Such mappings are created for the stack area on architectures\[em]for example, HP\-PARISC\[em]that have an upwardly growing stack.) .TP \fBPROT_GROWSDOWN\fP Применить режим защиты до начала отображения, которое растёт вниз (которое должно быть сегментом стека или сегментом, отображённым с установленным флагом \fBMAP_GROWSDOWN\fP). .PP Подобно \fBmprotect\fP(), вызов \fBpkey_mprotect\fP() изменяет защиту страниц, указанных \fIaddr\fP и \fIlen\fP. Аргумент \fIpkey\fP содержит ключ защиты (смотрите \fBpkeys\fP(7)), назначаемый памяти. Ключ защиты должен быть выделен с помощью \fBpkey_alloc\fP(2) до передачи в \fBpkey_mprotect\fP(). Пример использования этого системного вызова смотрите в \fBpkeys\fP(7). .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" On success, \fBmprotect\fP() and \fBpkey_mprotect\fP() return zero. On error, these system calls return \-1, and \fIerrno\fP is set to indicate the error. .SH ОШИБКИ .TP \fBEACCES\fP Нельзя задать этот вид доступа. Например, это может случиться, если при вызове \fBmmap\fP(2) файл доступен только на чтение, а запрос \fBmprotect\fP() был \fBPROT_WRITE\fP. .TP \fBEINVAL\fP Значение \fIaddr\fP не является правильным указателем или не кратен размеру системной страницы. .TP \fBEINVAL\fP (\fBpkey_mprotect\fP()) \fIpkey\fP не был выделен с помощью \fBpkey_alloc\fP(2). .TP \fBEINVAL\fP В \fIprot\fP указаны оба флага, \fBPROT_GROWSUP\fP и \fBPROT_GROWSDOWN\fP. .TP \fBEINVAL\fP Указано неверное значение в \fIprot\fP. .TP \fBEINVAL\fP (архитектура PowerPC ) В \fIprot\fP указан \fBPROT_SAO\fP, но недоступно аппаратное свойство SAO. .TP \fBENOMEM\fP Не удалось выделить место под внутренние структуры ядра. .TP \fBENOMEM\fP Addresses in the range [\fIaddr\fP, \fIaddr\fP+\fIlen\fP\-1] are invalid for the address space of the process, or specify one or more pages that are not mapped. (Before Linux 2.4.19, the error \fBEFAULT\fP was incorrectly produced for these cases.) .TP \fBENOMEM\fP .\" I.e., the number of VMAs would exceed the 64 kB maximum Изменение защиты области памяти привело бы к превышению разрешённого максимума на количество отображений с различающимися атрибутами (защита на чтение и на чтение/запись). Например, защита диапазона \fBPROT_READ\fP в середине области, которая сейчас защищена \fBPROT_READ|PROT_WRITE\fP, привела бы к трём отображениям: два отображения на концах, доступных на чтение/запись и доступное только для чтение отображение посередине. .SH ВЕРСИИ Вызов \fBpkey_mprotect\fP() впервые появился в Linux 4.9; поддержка в библиотеке glibc добавлена в версии 2.27. .SH СТАНДАРТЫ .\" SVr4 defines an additional error .\" code EAGAIN. The SVr4 error conditions don't map neatly onto Linux's. \fBmprotect\fP(): В POSIX.1\-2001, POSIX.1\-2008, SVr4 сказано, что поведение \fBmprotect\fP() не определено, если переданная область памяти не получена через \fBmmap\fP(2). .PP Вызов \fBpkey_mprotect\fP является непереносимым расширением Linux. .SH ЗАМЕЧАНИЯ В Linux всегда можно вызвать \fBmprotect\fP() с любым адресом из адресного пространства процесса (за исключением области ядра vsyscall). В частности, это можно использовать для изменения отображений существующего кода на записываемые. .PP Отличается ли действие \fBPROT_EXEC\fP от \fBPROT_READ\fP зависит от архитектуры процессора, версии ядра и состояния процесса. Если в флагах специализаций процессора установлен \fBREAD_IMPLIES_EXEC\fP (смотрите \fBpersonality\fP(2)), то указание \fBPROT_READ\fP подразумевает добавление \fBPROT_EXEC\fP. .PP На некоторых аппаратных архитектурах (например, i386) \fBPROT_WRITE\fP подразумевает \fBPROT_READ\fP. .PP В POSIX.1 сказано, что реализация может разрешить доступ отличный от указанного в \fIprot\fP, но для доступа на запись должен быть обязательно установлен флаг \fBPROT_WRITE\fP, и любой доступ должен быть запрещён, если установлен флаг \fBPROT_NONE\fP. .PP В приложениях нужно осторожно использовать \fBmprotect\fP() и \fBpkey_mprotect\fP() вместе. На x86, если \fBmprotect\fP() используется с установленным в \fIprot\fP значением \fBPROT_EXEC\fP, то pkey может быть выделен и установлен ядром в память неявным образом, но только если до этого pkey был равен 0. .PP В системах без аппаратной поддержки ключей защиты \fBpkey_mprotect\fP() всё ещё можно использовать, но значение \fIpkey\fP должно быть равно \-1. При таком вызове операция \fBpkey_mprotect\fP() эквивалентна \fBmprotect\fP(). .SH ПРИМЕРЫ .\" sigaction.2 refers to this example Программа, представленная далее, показывает использование \fBmprotect\fP(). Она выделяет четыре страницы памяти, делает третью доступной только на чтение, а затем запускает цикл, который проходит по выделенной области, меняя байты. .PP Результат работы программы: .PP .in +4n .EX $\fB ./a.out\fP Начало области: 0x804c000 Получен SIGSEGV при адресе: 0x804e000 .EE .in .SS "Исходный код программы" .\" SRC BEGIN (mprotect.c) \& .EX #include #include #include #include #include #include #define handle_error(msg) \e do { perror(msg); exit(EXIT_FAILURE); } while (0) static char *buffer; static void handler(int sig, siginfo_t *si, void *unused) { /* Замечание: вызов printf() из обработчика сигнала небезопасен (и не должен выполняться в готовых программах), так как printf() не async\-signal\-safe; смотрите signal\-safety(7). Тем не менее, здесь мы используем printf(), так как это простой способ показать когда вызывается обработчик. */ printf("Получен SIGSEGV при адресе: %p\en", si\->si_addr); exit(EXIT_FAILURE); } int main(void) { int pagesize; struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == \-1) handle_error("sigaction"); pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == \-1) handle_error("sysconf"); /* выделить буфер с выравниванием на границу страницы; начальная защита: PROT_READ | PROT_WRITE */ buffer = memalign(pagesize, 4 * pagesize); if (buffer == NULL) handle_error("memalign"); printf("Начало области: %p\en", buffer); if (mprotect(buffer + pagesize * 2, pagesize, PROT_READ) == \-1) handle_error("mprotect"); for (char *p = buffer ; ; ) *(p++) = \[aq]a\[aq]; printf("Цикл завершён\en"); /* никогда не должно случиться */ exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "СМ. ТАКЖЕ" \fBmmap\fP(2), \fBsysconf\fP(3), \fBpkeys\fP(7) .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан aereiae , Alexey , Azamat Hackimov , Dmitriy S. Seregin , Dmitry Bolkhovskikh , ITriskTI , Max Is , Yuri Kozlov , Иван Павлов и Малянов Евгений Викторович . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .