aboutsummaryrefslogtreecommitdiff
path: root/documentation/content/ru/books/arch-handbook/jail
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/content/ru/books/arch-handbook/jail')
-rw-r--r--documentation/content/ru/books/arch-handbook/jail/_index.adoc529
-rw-r--r--documentation/content/ru/books/arch-handbook/jail/_index.po1461
2 files changed, 1990 insertions, 0 deletions
diff --git a/documentation/content/ru/books/arch-handbook/jail/_index.adoc b/documentation/content/ru/books/arch-handbook/jail/_index.adoc
new file mode 100644
index 0000000000..14b36f4151
--- /dev/null
+++ b/documentation/content/ru/books/arch-handbook/jail/_index.adoc
@@ -0,0 +1,529 @@
+---
+description: 'Подсистема клеток'
+next: books/arch-handbook/sysinit
+params:
+ path: /books/arch-handbook/jail/
+prev: books/arch-handbook/kobj
+showBookMenu: 'true'
+tags: ["jail", "architecture", "networking", "kernel"]
+title: 'Глава 4. Подсистема клеток'
+weight: 5
+---
+
+[[jail]]
+= Подсистема клеток
+:doctype: book
+:toc: macro
+:toclevels: 1
+:icons: font
+:sectnums:
+:sectnumlevels: 6
+:sectnumoffset: 4
+:partnums:
+:source-highlighter: rouge
+:experimental:
+:images-path: books/arch-handbook/
+
+ifdef::env-beastie[]
+ifdef::backend-html5[]
+:imagesdir: ../../../../images/{images-path}
+endif::[]
+ifndef::book[]
+include::shared/authors.adoc[]
+include::shared/mirrors.adoc[]
+include::shared/releases.adoc[]
+include::shared/attributes/attributes-{{% lang %}}.adoc[]
+include::shared/{{% lang %}}/teams.adoc[]
+include::shared/{{% lang %}}/mailing-lists.adoc[]
+include::shared/{{% lang %}}/urls.adoc[]
+toc::[]
+endif::[]
+ifdef::backend-pdf,backend-epub3[]
+include::../../../../../shared/asciidoctor.adoc[]
+endif::[]
+endif::[]
+
+ifndef::env-beastie[]
+toc::[]
+include::../../../../../shared/asciidoctor.adoc[]
+endif::[]
+
+На большинстве систем UNIX(R) пользователь `root` обладает неограниченной властью. Это не способствует безопасности. Если злоумышленник получит права `root` в системе, у него окажутся все функции под рукой. В FreeBSD существуют sysctl-параметры, которые ограничивают власть `root`, чтобы минимизировать ущерб от действий злоумышленника. В частности, одна из таких функций называется `уровни безопасности`. Аналогично, другая функция, доступная начиная с FreeBSD 4.0, — это утилита man:jail[8] — клетка. Клетка создает chroot-окружение и накладывает определенные ограничения на процессы, запущенные внутри `клетки`. Например, процесс в `клетке` не может влиять на процессы вне её, использовать определенные системные вызовы или наносить какой-либо ущерб основной системе.
+
+Клетка становится новой моделью безопасности. Пользователи запускают потенциально уязвимые серверы, такие как Apache, BIND и sendmail, внутри клеток, так что если злоумышленник получит права `root` внутри клетки, это будет лишь неудобством, а не катастрофой. Данная статья в основном сосредоточена на внутреннем устройстве (исходном коде) клетки. Для получения информации о настройке клетки см. extref:{handbook}jails[раздел о клетках Руководства FreeBSD, jails-synopsis].
+
+[[jail-arch]]
+== Архитектура
+
+`Клетка` состоит из двух областей: пользовательской программы man:jail[8] и кода, реализованного в ядре: системного вызова man:jail[2] и связанных с ним ограничений. Я расскажу о пользовательской программе, а затем о том, как `клетка` реализована в ядре.
+
+=== Код в пользовательском пространстве
+
+Исходный код пользовательской части `клетки` находится в [.filename]#/usr/src/usr.sbin/jail# и состоит из одного файла [.filename]#jail.c#. Программа принимает следующие аргументы: путь к `клетке`, имя хоста, IP-адрес и команду для выполнения.
+
+==== Структуры данных
+
+В файле [.filename]#jail.c# первое, на что я бы обратил внимание, это объявление важной структуры `struct jail j;`, которая была включена из [.filename]#/usr/include/sys/jail.h#.
+
+Определение структуры `jail` выглядит следующим образом:
+
+[.programlisting]
+....
+/usr/include/sys/jail.h:
+
+struct jail {
+ u_int32_t version;
+ char *path;
+ char *hostname;
+ u_int32_t ip_number;
+};
+....
+
+Как видно, существует запись для каждого из аргументов, переданных программе man:jail[8], и действительно, они устанавливаются во время её выполнения.
+
+[.programlisting]
+....
+/usr/src/usr.sbin/jail/jail.c
+char path[PATH_MAX];
+...
+if (realpath(argv[0], path) == NULL)
+ err(1, "realpath: %s", argv[0]);
+if (chdir(path) != 0)
+ err(1, "chdir: %s", path);
+memset(&j, 0, sizeof(j));
+j.version = 0;
+j.path = path;
+j.hostname = argv[1];
+....
+
+==== Сетевое взаимодействие
+
+Один из аргументов, передаваемых программе man:jail[8], — это IP-адрес, по которому можно получить доступ к клетке через сеть. man:jail[8] преобразует указанный IP-адрес в порядок байтов хоста и сохраняет его в `j` (структура `jail`).
+
+[.programlisting]
+....
+/usr/src/usr.sbin/jail/jail.c:
+struct in_addr in;
+...
+if (inet_aton(argv[2], &in) == 0)
+ errx(1, "Could not make sense of ip-number: %s", argv[2]);
+j.ip_number = ntohl(in.s_addr);
+....
+
+Функция man:inet_aton[3] "интерпретирует указанную строку символов как интернет-адрес, помещая адрес в предоставленную структуру." Член структуры `ip_number` в структуре `jail` устанавливается только тогда, когда IP-адрес, помещённый в структуру `in` функцией man:inet_aton[3], преобразуется в порядок байтов хоста с помощью man:ntohl[3].
+
+==== Процесс в клетке
+
+Наконец, пользовательская программа помещает процесс в `клетку`. Теперь `клетка` становится самим заключенным процессом и выполняет команду, используя man:execv[3].
+
+[.programlisting]
+....
+/usr/src/usr.sbin/jail/jail.c
+i = jail(&j);
+...
+if (execv(argv[3], argv + 3) != 0)
+ err(1, "execv: %s", argv[3]);
+....
+
+Как видно, вызывается функция `jail()`, и её аргументом является структура `jail`, заполненная аргументами, переданными программе. В конце выполняется указанная вами программа. Теперь я расскажу о том, как `клетка` реализована в ядре.
+
+=== Пространство ядра системы
+
+Мы сейчас рассмотрим файл [.filename]#/usr/src/sys/kern/kern_jail.c#. В этом файле определены системный вызов man:jail[2], соответствующие sysctls и сетевые функции.
+
+==== Управляемые переменные ядра sysctl
+
+В файле [.filename]#kern_jail.c# определены следующие параметры sysctl:
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+int jail_set_hostname_allowed = 1;
+SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
+ &jail_set_hostname_allowed, 0,
+ "Processes in jail can set their hostnames");
+
+int jail_socket_unixiproute_only = 1;
+SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
+ &jail_socket_unixiproute_only, 0,
+ "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
+
+int jail_sysvipc_allowed = 0;
+SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
+ &jail_sysvipc_allowed, 0,
+ "Processes in jail can use System V IPC primitives");
+
+static int jail_enforce_statfs = 2;
+SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,
+ &jail_enforce_statfs, 0,
+ "Processes in jail cannot see all mounted file systems");
+
+int jail_allow_raw_sockets = 0;
+SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,
+ &jail_allow_raw_sockets, 0,
+ "Prison root can create raw sockets");
+
+int jail_chflags_allowed = 0;
+SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,
+ &jail_chflags_allowed, 0,
+ "Processes in jail can alter system file flags");
+
+int jail_mount_allowed = 0;
+SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
+ &jail_mount_allowed, 0,
+ "Processes in jail can mount/unmount jail-friendly file systems");
+....
+
+Каждый из этих параметров sysctl может быть доступен пользователю через программу man:sysctl[8]. В ядре эти конкретные параметры sysctl распознаются по их именам. Например, имя первого параметра sysctl — `security.jail.set_hostname_allowed`.
+
+==== Системный вызов man:jail[2]
+
+Как и все системные вызовы, системный вызов man:jail[2] принимает два аргумента: `struct thread *td` и `struct jail_args *uap`. `td` — это указатель на структуру `thread`, которая описывает вызывающий поток. В данном контексте `uap` — это указатель на структуру, в которой содержится указатель на структуру `jail`, переданную из пользовательского пространства [.filename]#jail.c#. Ранее, когда я описывал пользовательскую программу, вы видели, что системному вызову man:jail[2] была передана структура `jail` в качестве собственного аргумента.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+/*
+ * struct jail_args {
+ * struct jail *jail;
+ * };
+ */
+int
+jail(struct thread *td, struct jail_args *uap)
+....
+
+Следовательно, `uap->jail` можно использовать для доступа к структуре `jail`, которая была передана системному вызову. Далее системный вызов копирует структуру `клетка` в пространство ядра с помощью функции man:copyin[9]. man:copyin[9] принимает три аргумента: адрес данных, которые нужно скопировать в пространство ядра (`uap->jail`), место для записи данных (`j`) и размер хранилища. Структура `jail`, на которую указывает `uap->jail`, копируется в пространство ядра и сохраняется в другой структуре `клетка` — `j`.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+error = copyin(uap->jail, &j, sizeof(j));
+....
+
+В [.filename]#jail.h# определена ещё одна важная структура — `prison`. Структура `prison` используется исключительно в пространстве ядра. Вот определение структуры `prison`.
+
+[.programlisting]
+....
+/usr/include/sys/jail.h:
+struct prison {
+ LIST_ENTRY(prison) pr_list; /* (a) all prisons */
+ int pr_id; /* (c) prison id */
+ int pr_ref; /* (p) refcount */
+ char pr_path[MAXPATHLEN]; /* (c) chroot path */
+ struct vnode *pr_root; /* (c) vnode to rdir */
+ char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */
+ u_int32_t pr_ip; /* (c) ip addr host */
+ void *pr_linux; /* (p) linux abi */
+ int pr_securelevel; /* (p) securelevel */
+ struct task pr_task; /* (d) destroy task */
+ struct mtx pr_mtx;
+ void **pr_slots; /* (p) additional data */
+};
+....
+
+Системный вызов man:jail[2] затем выделяет память для структуры `prison` и копирует данные между структурой `клетка` и структурой `prison`.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
+...
+error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);
+if (error)
+ goto e_killmtx;
+...
+error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
+if (error)
+ goto e_dropvnref;
+pr->pr_ip = j.ip_number;
+....
+
+Далее мы рассмотрим ещё один важный системный вызов man:jail_attach[2], который реализует функцию помещения процесса в клетку.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+/*
+ * struct jail_attach_args {
+ * int jid;
+ * };
+ */
+int
+jail_attach(struct thread *td, struct jail_attach_args *uap)
+....
+
+Этот системный вызов вносит изменения, которые позволяют отличить процесс в клетке от процессов вне клетки. Чтобы понять, что делает man:jail_attach[2], необходима некоторая справочная информация.
+
+В FreeBSD каждый видимый ядром поток идентифицируется своей структурой `thread`, а процессы описываются их структурами `proc`. Определения структур `thread` и `proc` можно найти в [.filename]#/usr/include/sys/proc.h#. Например, аргумент `td` в любом системном вызове на самом деле является указателем на структуру `thread` вызывающего потока, как было указано ранее. Член `td_proc` в структуре `thread`, на которую указывает `td`, является указателем на структуру `proc`, представляющую процесс, содержащий поток, представленный структурой `td`. Структура `proc` содержит члены, которые могут описывать идентификацию владельца (`p_ucred`), ограничения ресурсов процесса (`p_limit`) и так далее. В структуре `ucred`, на которую указывает член `p_ucred` в структуре `proc`, есть указатель на структуру `prison` (`cr_prison`).
+
+[.programlisting]
+....
+/usr/include/sys/proc.h:
+struct thread {
+ ...
+ struct proc *td_proc;
+ ...
+};
+struct proc {
+ ...
+ struct ucred *p_ucred;
+ ...
+};
+/usr/include/sys/ucred.h
+struct ucred {
+ ...
+ struct prison *cr_prison;
+ ...
+};
+....
+
+В файле [.filename]#kern_jail.c# функция `jail()` вызывает функцию `jail_attach()` с заданным `jid`. Затем `jail_attach()` вызывает функцию `change_root()` для изменения корневого каталога вызывающего процесса. Функция `jail_attach()` создает новую структуру `ucred` и присоединяет её к вызывающему процессу после успешного присоединения структуры `prison` к структуре `ucred`. С этого момента вызывающий процесс считается находящимся в клетке. Когда в ядре вызывается функция `jailed()` с вновь созданной структурой `ucred` в качестве аргумента, она возвращает 1, указывая, что учётные данные связаны с клеткой. Общим родительским процессом для всех процессов, созданных внутри клетки, является процесс, запускающий man:jail[8], так как он вызывает системный вызов man:jail[2]. При выполнении программы через man:execve[2] она наследует свойство клетки из структуры `ucred` родительского процесса, следовательно, у нее структура `ucred` тоже со свойством клетки.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c
+int
+jail(struct thread *td, struct jail_args *uap)
+{
+...
+ struct jail_attach_args jaa;
+...
+ error = jail_attach(td, &jaa);
+ if (error)
+ goto e_dropprref;
+...
+}
+
+int
+jail_attach(struct thread *td, struct jail_attach_args *uap)
+{
+ struct proc *p;
+ struct ucred *newcred, *oldcred;
+ struct prison *pr;
+...
+ p = td->td_proc;
+...
+ pr = prison_find(uap->jid);
+...
+ change_root(pr->pr_root, td);
+...
+ newcred->cr_prison = pr;
+ p->p_ucred = newcred;
+...
+}
+....
+
+Когда процесс создается из родительского процесса, системный вызов man:fork[2] использует `crhold()` для поддержания учетных данных нового процесса. Это автоматически сохраняет учетные данные нового дочернего процесса согласованными с родительским, поэтому дочерний процесс также остается в клетке.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_fork.c:
+p2->p_ucred = crhold(td->td_ucred);
+...
+td2->td_ucred = crhold(p2->p_ucred);
+....
+
+[[jail-restrictions]]
+== Ограничения
+
+В ядре существуют ограничения доступа, связанные с процессами в клетках. Обычно эти ограничения просто проверяют, находится ли процесс в клетке, и если да, возвращают ошибку. Например:
+
+[.programlisting]
+....
+if (jailed(td->td_ucred))
+ return (EPERM);
+....
+
+=== SysV IPC
+
+System V IPC основан на сообщениях. Процессы могут отправлять друг другу эти сообщения, которые указывают им, как действовать. Функции, работающие с сообщениями: man:msgctl[3], man:msgget[3], man:msgsnd[3] и man:msgrcv[3]. Ранее я упоминал, что существуют определённые sysctl, которые можно включать или выключать для изменения поведения клетки. Один из таких sysctl — `security.jail.sysvipc_allowed`. По умолчанию этот sysctl установлен в 0. Если бы он был установлен в 1, это бы свело на нет весь смысл клетки: привилегированные пользователи внутри клетки смогли бы влиять на процессы за её пределами. Разница между сообщением и сигналом заключается в том, что сообщение состоит только из номера сигнала.
+
+[.filename]#/usr/src/sys/kern/sysv_msg.c#:
+
+* `msgget(key, msgflg)`: `msgget` возвращает (и, возможно, создаёт) дескриптор сообщения, который обозначает очередь сообщений для использования в других функциях.
+* `msgctl(msgid, cmd, buf)`: С помощью этой функции процесс может запросить статус дескриптора сообщения.
+* `msgsnd(msgid, msgp, msgsz, msgflg)`: `msgsnd` отправляет сообщение процессу.
+* `msgrcv(msgid, msgp, msgsz, msgtyp, msgflg)`: процесс получает сообщения с помощью этой функции
+
+В каждом из системных вызовов, соответствующих этим функциям, присутствует следующее условие:
+
+[.programlisting]
+....
+/usr/src/sys/kern/sysv_msg.c:
+if (!jail_sysvipc_allowed && jailed(td->td_ucred))
+ return (ENOSYS);
+....
+
+Системные вызовы семафоров позволяют процессам синхронизировать выполнение, атомарно выполняя набор операций над набором семафоров. По сути, семафоры предоставляют ещё один способ для процессов блокировать ресурсы. Однако процесс, ожидающий семафор, который уже используется, будет находиться в состоянии сна до тех пор, пока ресурсы не будут освобождены. Следующие системные вызовы семафоров блокируются внутри клетки: man:semget[2], man:semctl[2] и man:semop[2].
+
+[.filename]#/usr/src/sys/kern/sysv_sem.c#:
+
+* `semctl(semid, semnum, cmd, ...)`: `semctl` выполняет указанную команду `cmd` для очереди семафоров, указанной в `semid`.
+* `semget(key, nsems, flag)`: `semget` создает массив семафоров, соответствующих `key`.
++
+`key и flag имеют то же значение, как и в msgget.`
+* `semop(semid, array, nops)`: `semop` выполняет набор операций, указанных в `array`, для набора семафоров, идентифицируемых `semid`.
+
+Система IPC System V позволяет процессам использовать общую память. Процессы могут взаимодействовать напрямую друг с другом, разделяя части своего виртуального адресного пространства и затем читая и записывая данные в общей памяти. Эти системные вызовы заблокированы в среде _клетки_: man:shmdt[2], man:shmat[2], man:shmctl[2] и man:shmget[2].
+
+[.filename]#/usr/src/sys/kern/sysv_shm.c#:
+
+* `shmctl(shmid, cmd, buf)`: `shmctl` выполняет различные управляющие операции над областью разделяемой памяти, идентифицируемой `shmid`.
+* `shmget(key, size, flag)`: `shmget` обращается к существующей или создает новую область разделяемой памяти размером `size` байт.
+* `shmat(shmid, addr, flag)`: `shmat` присоединяет область разделяемой памяти, идентифицируемую `shmid`, к адресному пространству процесса.
+* `shmdt(addr)`: `shmdt` отсоединяет ранее присоединенную область разделяемой памяти по адресу `addr`.
+
+=== Сокеты
+
+Клетка обрабатывает системный вызов man:socket[2] и связанные низкоуровневые функции сокетов особым образом. Для определения, разрешено ли создание определённого сокета, сначала проверяется значение sysctl `security.jail.socket_unixiproute_only`. Если оно установлено, сокеты разрешено создавать только в случае, если указанное семейство равно `PF_LOCAL`, `PF_INET` или `PF_ROUTE`. В противном случае возвращается ошибка.
+
+[.programlisting]
+....
+/usr/src/sys/kern/uipc_socket.c:
+int
+socreate(int dom, struct socket **aso, int type, int proto,
+ struct ucred *cred, struct thread *td)
+{
+ struct protosw *prp;
+...
+ if (jailed(cred) && jail_socket_unixiproute_only &&
+ prp->pr_domain->dom_family != PF_LOCAL &&
+ prp->pr_domain->dom_family != PF_INET &&
+ prp->pr_domain->dom_family != PF_ROUTE) {
+ return (EPROTONOSUPPORT);
+ }
+...
+}
+....
+
+=== Berkeley Packet Filter
+
+Берклиевский фильтр пакетов (BPF) предоставляет низкоуровневый интерфейс к канальному уровню, независимый от протокола. В настоящее время BPF управляется через man:devfs[8], который определяет возможность его использования в клетке.
+
+=== Протоколы
+
+Существуют определенные протоколы, которые очень распространены, такие как TCP, UDP, IP и ICMP. IP и ICMP находятся на одном уровне: сетевом уровне 2. Принимаются определенные меры предосторожности, чтобы предотвратить привязку протокола к определенному адресу процессом в клетке, только если установлен параметр `nam`. `nam` является указателем на структуру `sockaddr`, которая описывает адрес, к которому привязывается служба. Более точное определение заключается в том, что `sockaddr` "может использоваться как шаблон для ссылки на идентификационный тег и длину каждого адреса". В функции `in_pcbbind_setup()`, `sin` — это указатель на структуру `sockaddr_in`, которая содержит порт, адрес, длину и семейство доменов сокета, который должен быть привязан. В основном, это запрещает любым процессам из клетки указывать адрес, который не принадлежит клетке, в которой существует вызывающий процесс.
+
+[.programlisting]
+....
+/usr/src/sys/netinet/in_pcb.c:
+int
+in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
+ u_short *lportp, struct ucred *cred)
+{
+ ...
+ struct sockaddr_in *sin;
+ ...
+ if (nam) {
+ sin = (struct sockaddr_in *)nam;
+ ...
+ if (sin->sin_addr.s_addr != INADDR_ANY)
+ if (prison_ip(cred, 0, &sin->sin_addr.s_addr))
+ return(EINVAL);
+ ...
+ if (lport) {
+ ...
+ if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
+ return (EADDRNOTAVAIL);
+ ...
+ }
+ }
+ if (lport == 0) {
+ ...
+ if (laddr.s_addr != INADDR_ANY)
+ if (prison_ip(cred, 0, &laddr.s_addr))
+ return (EINVAL);
+ ...
+ }
+...
+ if (prison_ip(cred, 0, &laddr.s_addr))
+ return (EINVAL);
+...
+}
+....
+
+Вы можете задаться вопросом, какую функцию выполняет `prison_ip()`. `prison_ip()` принимает три аргумента: указатель на учетные данные (представленные как `cred`), любые флаги и IP-адрес. Она возвращает 1, если IP-адрес НЕ принадлежит клетке, и 0 в противном случае. Как видно из кода, если это действительно IP-адрес, не принадлежащий клетке, протоколу не разрешается привязываться к этому адресу.
+
+[.programlisting]
+....
+/usr/src/sys/kern/kern_jail.c:
+int
+prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
+{
+ u_int32_t tmp;
+
+ if (!jailed(cred))
+ return (0);
+ if (flag)
+ tmp = *ip;
+ else
+ tmp = ntohl(*ip);
+ if (tmp == INADDR_ANY) {
+ if (flag)
+ *ip = cred->cr_prison->pr_ip;
+ else
+ *ip = htonl(cred->cr_prison->pr_ip);
+ return (0);
+ }
+ if (tmp == INADDR_LOOPBACK) {
+ if (flag)
+ *ip = cred->cr_prison->pr_ip;
+ else
+ *ip = htonl(cred->cr_prison->pr_ip);
+ return (0);
+ }
+ if (cred->cr_prison->pr_ip != tmp)
+ return (1);
+ return (0);
+}
+....
+
+=== Файловая система
+
+Даже пользователи с правами `root` внутри `клетки` не могут снять или изменить любые флаги файлов, такие как неизменяемый, только для добавления и неудаляемый, если уровень безопасности (`securelevel`) больше 0.
+
+[.programlisting]
+....
+/usr/src/sys/ufs/ufs/ufs_vnops.c:
+static int
+ufs_setattr(ap)
+ ...
+{
+ ...
+ if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
+ if (ip->i_flags
+ & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
+ error = securelevel_gt(cred, 0);
+ if (error)
+ return (error);
+ }
+ ...
+ }
+}
+/usr/src/sys/kern/kern_priv.c
+int
+priv_check_cred(struct ucred *cred, int priv, int flags)
+{
+ ...
+ error = prison_priv_check(cred, priv);
+ if (error)
+ return (error);
+ ...
+}
+/usr/src/sys/kern/kern_jail.c
+int
+prison_priv_check(struct ucred *cred, int priv)
+{
+ ...
+ switch (priv) {
+ ...
+ case PRIV_VFS_SYSFLAGS:
+ if (jail_chflags_allowed)
+ return (0);
+ else
+ return (EPERM);
+ ...
+ }
+ ...
+}
+....
diff --git a/documentation/content/ru/books/arch-handbook/jail/_index.po b/documentation/content/ru/books/arch-handbook/jail/_index.po
new file mode 100644
index 0000000000..893ba88f10
--- /dev/null
+++ b/documentation/content/ru/books/arch-handbook/jail/_index.po
@@ -0,0 +1,1461 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR The FreeBSD Project
+# This file is distributed under the same license as the FreeBSD Documentation package.
+# Vladlen Popolitov <vladlenpopolitov@list.ru>, 2025.
+msgid ""
+msgstr ""
+"Project-Id-Version: FreeBSD Documentation VERSION\n"
+"POT-Creation-Date: 2025-05-01 19:56-0300\n"
+"PO-Revision-Date: 2025-10-16 04:45+0000\n"
+"Last-Translator: Vladlen Popolitov <vladlenpopolitov@list.ru>\n"
+"Language-Team: Russian <https://translate-dev.freebsd.org/projects/"
+"documentation/booksarch-handbookjail_index/ru/>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 4.17\n"
+
+#. type: Title =
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:1
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:14
+#, no-wrap
+msgid "The Jail Subsystem"
+msgstr "Подсистема клеток"
+
+#. type: YAML Front Matter: title
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:1
+#, no-wrap
+msgid "Chapter 4. The Jail Subsystem"
+msgstr "Глава 4. Подсистема клеток"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:52
+msgid ""
+"On most UNIX(R) systems, `root` has omnipotent power. This promotes "
+"insecurity. If an attacker gained `root` on a system, he would have every "
+"function at his fingertips. In FreeBSD there are sysctls which dilute the "
+"power of `root`, in order to minimize the damage caused by an attacker. "
+"Specifically, one of these functions is called `secure levels`. Similarly, "
+"another function which is present from FreeBSD 4.0 and onward, is a utility "
+"called man:jail[8]. Jail chroots an environment and sets certain "
+"restrictions on processes which are forked within the jail. For example, a "
+"jailed process cannot affect processes outside the jail, utilize certain "
+"system calls, or inflict any damage on the host environment."
+msgstr ""
+"На большинстве систем UNIX(R) пользователь `root` обладает неограниченной "
+"властью. Это не способствует безопасности. Если злоумышленник получит права "
+"`root` в системе, у него окажутся все функции под рукой. В FreeBSD "
+"существуют sysctl-параметры, которые ограничивают власть `root`, чтобы "
+"минимизировать ущерб от действий злоумышленника. В частности, одна из таких "
+"функций называется `уровни безопасности`. Аналогично, другая функция, "
+"доступная начиная с FreeBSD 4.0, — это утилита man:jail[8] — клетка. Клетка "
+"создает chroot-окружение и накладывает определенные ограничения на процессы, "
+"запущенные внутри `клетки`. Например, процесс в `клетке` не может влиять на "
+"процессы вне её, использовать определенные системные вызовы или наносить "
+"какой-либо ущерб основной системе."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:54
+msgid ""
+"Jail is becoming the new security model. People are running potentially "
+"vulnerable servers such as Apache, BIND, and sendmail within jails, so that "
+"if an attacker gains `root` within the jail, it is only an annoyance, and "
+"not a devastation. This article mainly focuses on the internals (source "
+"code) of jail. For information on how to set up a jail see the extref:"
+"{handbook}[handbook entry on jails, jails]."
+msgstr ""
+"Клетка становится новой моделью безопасности. Пользователи запускают "
+"потенциально уязвимые серверы, такие как Apache, BIND и sendmail, внутри "
+"клеток, так что если злоумышленник получит права `root` внутри клетки, это "
+"будет лишь неудобством, а не катастрофой. Данная статья в основном "
+"сосредоточена на внутреннем устройстве (исходном коде) клетки. Для получения "
+"информации о настройке клетки см. extref:{handbook}jails[раздел о клетках "
+"Руководства FreeBSD, jails-synopsis]."
+
+#. type: Title ==
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:56
+#, no-wrap
+msgid "Architecture"
+msgstr "Архитектура"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:59
+msgid ""
+"Jail consists of two realms: the userland program, man:jail[8], and the code "
+"implemented within the kernel: the man:jail[2] system call and associated "
+"restrictions. I will be discussing the userland program and then how jail is "
+"implemented within the kernel."
+msgstr ""
+"`Клетка` состоит из двух областей: пользовательской программы man:jail[8] и "
+"кода, реализованного в ядре: системного вызова man:jail[2] и связанных с ним "
+"ограничений. Я расскажу о пользовательской программе, а затем о том, как "
+"`клетка` реализована в ядре."
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:60
+#, no-wrap
+msgid "Userland Code"
+msgstr "Код в пользовательском пространстве"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:63
+msgid ""
+"The source for the userland jail is located in [.filename]#/usr/src/usr.sbin/"
+"jail#, consisting of one file, [.filename]#jail.c#. The program takes these "
+"arguments: the path of the jail, hostname, IP address, and the command to be "
+"executed."
+msgstr ""
+"Исходный код пользовательской части `клетки` находится в [.filename]#/usr/"
+"src/usr.sbin/jail# и состоит из одного файла [.filename]#jail.c#. Программа "
+"принимает следующие аргументы: путь к `клетке`, имя хоста, IP-адрес и "
+"команду для выполнения."
+
+#. type: Title ====
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:64
+#, no-wrap
+msgid "Data Structures"
+msgstr "Структуры данных"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:67
+msgid ""
+"In [.filename]#jail.c#, the first thing I would note is the declaration of "
+"an important structure `struct jail j;` which was included from [.filename]#/"
+"usr/include/sys/jail.h#."
+msgstr ""
+"В файле [.filename]#jail.c# первое, на что я бы обратил внимание, это "
+"объявление важной структуры `struct jail j;`, которая была включена из [."
+"filename]#/usr/include/sys/jail.h#."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:69
+msgid "The definition of the `jail` structure is:"
+msgstr "Определение структуры `jail` выглядит следующим образом:"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:73
+#, no-wrap
+msgid "/usr/include/sys/jail.h:\n"
+msgstr "/usr/include/sys/jail.h:\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:80
+#, no-wrap
+msgid ""
+"struct jail {\n"
+" u_int32_t version;\n"
+" char *path;\n"
+" char *hostname;\n"
+" u_int32_t ip_number;\n"
+"};\n"
+msgstr ""
+"struct jail {\n"
+" u_int32_t version;\n"
+" char *path;\n"
+" char *hostname;\n"
+" u_int32_t ip_number;\n"
+"};\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:83
+msgid ""
+"As you can see, there is an entry for each of the arguments passed to the "
+"man:jail[8] program, and indeed, they are set during its execution."
+msgstr ""
+"Как видно, существует запись для каждого из аргументов, переданных программе "
+"man:jail[8], и действительно, они устанавливаются во время её выполнения."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:97
+#, no-wrap
+msgid ""
+"/usr/src/usr.sbin/jail/jail.c\n"
+"char path[PATH_MAX];\n"
+"...\n"
+"if (realpath(argv[0], path) == NULL)\n"
+" err(1, \"realpath: %s\", argv[0]);\n"
+"if (chdir(path) != 0)\n"
+" err(1, \"chdir: %s\", path);\n"
+"memset(&j, 0, sizeof(j));\n"
+"j.version = 0;\n"
+"j.path = path;\n"
+"j.hostname = argv[1];\n"
+msgstr ""
+"/usr/src/usr.sbin/jail/jail.c\n"
+"char path[PATH_MAX];\n"
+"...\n"
+"if (realpath(argv[0], path) == NULL)\n"
+" err(1, \"realpath: %s\", argv[0]);\n"
+"if (chdir(path) != 0)\n"
+" err(1, \"chdir: %s\", path);\n"
+"memset(&j, 0, sizeof(j));\n"
+"j.version = 0;\n"
+"j.path = path;\n"
+"j.hostname = argv[1];\n"
+
+#. type: Title ====
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:99
+#, no-wrap
+msgid "Networking"
+msgstr "Сетевое взаимодействие"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:102
+msgid ""
+"One of the arguments passed to the man:jail[8] program is an IP address with "
+"which the jail can be accessed over the network. man:jail[8] translates the "
+"IP address given into host byte order and then stores it in `j` (the `jail` "
+"structure)."
+msgstr ""
+"Один из аргументов, передаваемых программе man:jail[8], — это IP-адрес, по "
+"которому можно получить доступ к клетке через сеть. man:jail[8] преобразует "
+"указанный IP-адрес в порядок байтов хоста и сохраняет его в `j` (структура "
+"`jail`)."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:111
+#, no-wrap
+msgid ""
+"/usr/src/usr.sbin/jail/jail.c:\n"
+"struct in_addr in;\n"
+"...\n"
+"if (inet_aton(argv[2], &in) == 0)\n"
+" errx(1, \"Could not make sense of ip-number: %s\", argv[2]);\n"
+"j.ip_number = ntohl(in.s_addr);\n"
+msgstr ""
+"/usr/src/usr.sbin/jail/jail.c:\n"
+"struct in_addr in;\n"
+"...\n"
+"if (inet_aton(argv[2], &in) == 0)\n"
+" errx(1, \"Could not make sense of ip-number: %s\", argv[2]);\n"
+"j.ip_number = ntohl(in.s_addr);\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:114
+msgid ""
+"The man:inet_aton[3] function \"interprets the specified character string as "
+"an Internet address, placing the address into the structure provided.\" The "
+"`ip_number` member in the `jail` structure is set only when the IP address "
+"placed onto the `in` structure by man:inet_aton[3] is translated into host "
+"byte order by man:ntohl[3]."
+msgstr ""
+"Функция man:inet_aton[3] \"интерпретирует указанную строку символов как "
+"интернет-адрес, помещая адрес в предоставленную структуру.\" Член структуры "
+"`ip_number` в структуре `jail` устанавливается только тогда, когда IP-адрес, "
+"помещённый в структуру `in` функцией man:inet_aton[3], преобразуется в "
+"порядок байтов хоста с помощью man:ntohl[3]."
+
+#. type: Title ====
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:115
+#, no-wrap
+msgid "Jailing the Process"
+msgstr "Процесс в клетке"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:118
+msgid ""
+"Finally, the userland program jails the process. Jail now becomes an "
+"imprisoned process itself and then executes the command given using "
+"man:execv[3]."
+msgstr ""
+"Наконец, пользовательская программа помещает процесс в `клетку`. Теперь "
+"`клетка` становится самим заключенным процессом и выполняет команду, "
+"используя man:execv[3]."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:126
+#, no-wrap
+msgid ""
+"/usr/src/usr.sbin/jail/jail.c\n"
+"i = jail(&j);\n"
+"...\n"
+"if (execv(argv[3], argv + 3) != 0)\n"
+" err(1, \"execv: %s\", argv[3]);\n"
+msgstr ""
+"/usr/src/usr.sbin/jail/jail.c\n"
+"i = jail(&j);\n"
+"...\n"
+"if (execv(argv[3], argv + 3) != 0)\n"
+" err(1, \"execv: %s\", argv[3]);\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:129
+msgid ""
+"As you can see, the `jail()` function is called, and its argument is the "
+"`jail` structure which has been filled with the arguments given to the "
+"program. Finally, the program you specify is executed. I will now discuss "
+"how jail is implemented within the kernel."
+msgstr ""
+"Как видно, вызывается функция `jail()`, и её аргументом является структура "
+"`jail`, заполненная аргументами, переданными программе. В конце выполняется "
+"указанная вами программа. Теперь я расскажу о том, как `клетка` реализована "
+"в ядре."
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:130
+#, no-wrap
+msgid "Kernel Space"
+msgstr "Пространство ядра системы"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:133
+msgid ""
+"We will now be looking at the file [.filename]#/usr/src/sys/kern/"
+"kern_jail.c#. This is the file where the man:jail[2] system call, "
+"appropriate sysctls, and networking functions are defined."
+msgstr ""
+"Мы сейчас рассмотрим файл [.filename]#/usr/src/sys/kern/kern_jail.c#. В этом "
+"файле определены системный вызов man:jail[2], соответствующие sysctls и "
+"сетевые функции."
+
+#. type: Title ====
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:134
+#, no-wrap
+msgid "Sysctls"
+msgstr "Управляемые переменные ядра sysctl"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:137
+msgid "In [.filename]#kern_jail.c#, the following sysctls are defined:"
+msgstr "В файле [.filename]#kern_jail.c# определены следующие параметры sysctl:"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:145
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"int jail_set_hostname_allowed = 1;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,\n"
+" &jail_set_hostname_allowed, 0,\n"
+" \"Processes in jail can set their hostnames\");\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"int jail_set_hostname_allowed = 1;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,\n"
+" &jail_set_hostname_allowed, 0,\n"
+" \"Processes in jail can set their hostnames\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:150
+#, no-wrap
+msgid ""
+"int jail_socket_unixiproute_only = 1;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,\n"
+" &jail_socket_unixiproute_only, 0,\n"
+" \"Processes in jail are limited to creating UNIX/IPv4/route sockets only\");\n"
+msgstr ""
+"int jail_socket_unixiproute_only = 1;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,\n"
+" &jail_socket_unixiproute_only, 0,\n"
+" \"Processes in jail are limited to creating UNIX/IPv4/route sockets "
+"only\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:155
+#, no-wrap
+msgid ""
+"int jail_sysvipc_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,\n"
+" &jail_sysvipc_allowed, 0,\n"
+" \"Processes in jail can use System V IPC primitives\");\n"
+msgstr ""
+"int jail_sysvipc_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,\n"
+" &jail_sysvipc_allowed, 0,\n"
+" \"Processes in jail can use System V IPC primitives\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:160
+#, no-wrap
+msgid ""
+"static int jail_enforce_statfs = 2;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,\n"
+" &jail_enforce_statfs, 0,\n"
+" \"Processes in jail cannot see all mounted file systems\");\n"
+msgstr ""
+"static int jail_enforce_statfs = 2;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,\n"
+" &jail_enforce_statfs, 0,\n"
+" \"Processes in jail cannot see all mounted file systems\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:165
+#, no-wrap
+msgid ""
+"int jail_allow_raw_sockets = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,\n"
+" &jail_allow_raw_sockets, 0,\n"
+" \"Prison root can create raw sockets\");\n"
+msgstr ""
+"int jail_allow_raw_sockets = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,\n"
+" &jail_allow_raw_sockets, 0,\n"
+" \"Prison root can create raw sockets\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:170
+#, no-wrap
+msgid ""
+"int jail_chflags_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,\n"
+" &jail_chflags_allowed, 0,\n"
+" \"Processes in jail can alter system file flags\");\n"
+msgstr ""
+"int jail_chflags_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,\n"
+" &jail_chflags_allowed, 0,\n"
+" \"Processes in jail can alter system file flags\");\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:175
+#, no-wrap
+msgid ""
+"int jail_mount_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,\n"
+" &jail_mount_allowed, 0,\n"
+" \"Processes in jail can mount/unmount jail-friendly file systems\");\n"
+msgstr ""
+"int jail_mount_allowed = 0;\n"
+"SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,\n"
+" &jail_mount_allowed, 0,\n"
+" \"Processes in jail can mount/unmount jail-friendly file systems\");\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:178
+msgid ""
+"Each of these sysctls can be accessed by the user through the man:sysctl[8] "
+"program. Throughout the kernel, these specific sysctls are recognized by "
+"their name. For example, the name of the first sysctl is "
+"`security.jail.set_hostname_allowed`."
+msgstr ""
+"Каждый из этих параметров sysctl может быть доступен пользователю через "
+"программу man:sysctl[8]. В ядре эти конкретные параметры sysctl распознаются "
+"по их именам. Например, имя первого параметра sysctl — `security.jail."
+"set_hostname_allowed`."
+
+#. type: Title ====
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:179
+#, no-wrap
+msgid "man:jail[2] System Call"
+msgstr "Системный вызов man:jail[2]"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:182
+msgid ""
+"Like all system calls, the man:jail[2] system call takes two arguments, "
+"`struct thread *td` and `struct jail_args *uap`. `td` is a pointer to the "
+"`thread` structure which describes the calling thread. In this context, "
+"`uap` is a pointer to the structure in which a pointer to the `jail` "
+"structure passed by the userland [.filename]#jail.c# is contained. When I "
+"described the userland program before, you saw that the man:jail[2] system "
+"call was given a `jail` structure as its own argument."
+msgstr ""
+"Как и все системные вызовы, системный вызов man:jail[2] принимает два "
+"аргумента: `struct thread *td` и `struct jail_args *uap`. `td` — это "
+"указатель на структуру `thread`, которая описывает вызывающий поток. В "
+"данном контексте `uap` — это указатель на структуру, в которой содержится "
+"указатель на структуру `jail`, переданную из пользовательского пространства ["
+".filename]#jail.c#. Ранее, когда я описывал пользовательскую программу, вы "
+"видели, что системному вызову man:jail[2] была передана структура `jail` в "
+"качестве собственного аргумента."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:193
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"/*\n"
+" * struct jail_args {\n"
+" * struct jail *jail;\n"
+" * };\n"
+" */\n"
+"int\n"
+"jail(struct thread *td, struct jail_args *uap)\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"/*\n"
+" * struct jail_args {\n"
+" * struct jail *jail;\n"
+" * };\n"
+" */\n"
+"int\n"
+"jail(struct thread *td, struct jail_args *uap)\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:196
+msgid ""
+"Therefore, `uap->jail` can be used to access the `jail` structure which was "
+"passed to the system call. Next, the system call copies the `jail` structure "
+"into kernel space using the man:copyin[9] function. man:copyin[9] takes "
+"three arguments: the address of the data which is to be copied into kernel "
+"space, `uap->jail`, where to store it, `j` and the size of the storage. The "
+"`jail` structure pointed by `uap->jail` is copied into kernel space and is "
+"stored in another `jail` structure, `j`."
+msgstr ""
+"Следовательно, `uap->jail` можно использовать для доступа к структуре `jail`"
+", которая была передана системному вызову. Далее системный вызов копирует "
+"структуру `клетка` в пространство ядра с помощью функции man:copyin[9]. "
+"man:copyin[9] принимает три аргумента: адрес данных, которые нужно "
+"скопировать в пространство ядра (`uap->jail`), место для записи данных (`j`) "
+"и размер хранилища. Структура `jail`, на которую указывает `uap->jail`, "
+"копируется в пространство ядра и сохраняется в другой структуре `клетка` — "
+"`j`."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:201
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"error = copyin(uap->jail, &j, sizeof(j));\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"error = copyin(uap->jail, &j, sizeof(j));\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:204
+msgid ""
+"There is another important structure defined in [.filename]#jail.h#. It is "
+"the `prison` structure. The `prison` structure is used exclusively within "
+"kernel space. Here is the definition of the `prison` structure."
+msgstr ""
+"В [.filename]#jail.h# определена ещё одна важная структура — `prison`. "
+"Структура `prison` используется исключительно в пространстве ядра. Вот "
+"определение структуры `prison`."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:222
+#, no-wrap
+msgid ""
+"/usr/include/sys/jail.h:\n"
+"struct prison {\n"
+" LIST_ENTRY(prison) pr_list; /* (a) all prisons */\n"
+" int pr_id; /* (c) prison id */\n"
+" int pr_ref; /* (p) refcount */\n"
+" char pr_path[MAXPATHLEN]; /* (c) chroot path */\n"
+" struct vnode *pr_root; /* (c) vnode to rdir */\n"
+" char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */\n"
+" u_int32_t pr_ip; /* (c) ip addr host */\n"
+" void *pr_linux; /* (p) linux abi */\n"
+" int pr_securelevel; /* (p) securelevel */\n"
+" struct task pr_task; /* (d) destroy task */\n"
+" struct mtx pr_mtx;\n"
+" void **pr_slots; /* (p) additional data */\n"
+"};\n"
+msgstr ""
+"/usr/include/sys/jail.h:\n"
+"struct prison {\n"
+" LIST_ENTRY(prison) pr_list; /* (a) all prisons */"
+"\n"
+" int pr_id; /* (c) prison id */\n"
+" int pr_ref; /* (p) refcount */\n"
+" char pr_path[MAXPATHLEN]; /* (c) chroot path */"
+"\n"
+" struct vnode *pr_root; /* (c) vnode to rdir "
+"*/\n"
+" char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname "
+"*/\n"
+" u_int32_t pr_ip; /* (c) ip addr host "
+"*/\n"
+" void *pr_linux; /* (p) linux abi */\n"
+" int pr_securelevel; /* (p) securelevel */"
+"\n"
+" struct task pr_task; /* (d) destroy task "
+"*/\n"
+" struct mtx pr_mtx;\n"
+" void **pr_slots; /* (p) additional data "
+"*/\n"
+"};\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:225
+msgid ""
+"The man:jail[2] system call then allocates memory for a `prison` structure "
+"and copies data between the `jail` and `prison` structure."
+msgstr ""
+"Системный вызов man:jail[2] затем выделяет память для структуры `prison` и "
+"копирует данные между структурой `клетка` и структурой `prison`."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:239
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);\n"
+"...\n"
+"error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);\n"
+"if (error)\n"
+" goto e_killmtx;\n"
+"...\n"
+"error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);\n"
+"if (error)\n"
+" goto e_dropvnref;\n"
+"pr->pr_ip = j.ip_number;\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);\n"
+"...\n"
+"error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);\n"
+"if (error)\n"
+" goto e_killmtx;\n"
+"...\n"
+"error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);\n"
+"if (error)\n"
+" goto e_dropvnref;\n"
+"pr->pr_ip = j.ip_number;\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:242
+msgid ""
+"Next, we will discuss another important system call man:jail_attach[2], "
+"which implements the function to put a process into the jail."
+msgstr ""
+"Далее мы рассмотрим ещё один важный системный вызов man:jail_attach[2], "
+"который реализует функцию помещения процесса в клетку."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:253
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"/*\n"
+" * struct jail_attach_args {\n"
+" * int jid;\n"
+" * };\n"
+" */\n"
+"int\n"
+"jail_attach(struct thread *td, struct jail_attach_args *uap)\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"/*\n"
+" * struct jail_attach_args {\n"
+" * int jid;\n"
+" * };\n"
+" */\n"
+"int\n"
+"jail_attach(struct thread *td, struct jail_attach_args *uap)\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:256
+msgid ""
+"This system call makes the changes that can distinguish a jailed process "
+"from those unjailed ones. To understand what man:jail_attach[2] does for us, "
+"certain background information is needed."
+msgstr ""
+"Этот системный вызов вносит изменения, которые позволяют отличить процесс в "
+"клетке от процессов вне клетки. Чтобы понять, что делает man:jail_attach[2], "
+"необходима некоторая справочная информация."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:258
+msgid ""
+"On FreeBSD, each kernel visible thread is identified by its `thread` "
+"structure, while the processes are described by their `proc` structures. You "
+"can find the definitions of the `thread` and `proc` structure in "
+"[.filename]#/usr/include/sys/proc.h#. For example, the `td` argument in any "
+"system call is actually a pointer to the calling thread's `thread` "
+"structure, as stated before. The `td_proc` member in the `thread` structure "
+"pointed by `td` is a pointer to the `proc` structure which represents the "
+"process that contains the thread represented by `td`. The `proc` structure "
+"contains members which can describe the owner's identity(`p_ucred`), the "
+"process resource limits(`p_limit`), and so on. In the `ucred` structure "
+"pointed by `p_ucred` member in the `proc` structure, there is a pointer to "
+"the `prison` structure(`cr_prison`)."
+msgstr ""
+"В FreeBSD каждый видимый ядром поток идентифицируется своей структурой "
+"`thread`, а процессы описываются их структурами `proc`. Определения структур "
+"`thread` и `proc` можно найти в [.filename]#/usr/include/sys/proc.h#. "
+"Например, аргумент `td` в любом системном вызове на самом деле является "
+"указателем на структуру `thread` вызывающего потока, как было указано ранее. "
+"Член `td_proc` в структуре `thread`, на которую указывает `td`, является "
+"указателем на структуру `proc`, представляющую процесс, содержащий поток, "
+"представленный структурой `td`. Структура `proc` содержит члены, которые "
+"могут описывать идентификацию владельца (`p_ucred`), ограничения ресурсов "
+"процесса (`p_limit`) и так далее. В структуре `ucred`, на которую указывает "
+"член `p_ucred` в структуре `proc`, есть указатель на структуру `prison` "
+"(`cr_prison`)."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:278
+#, no-wrap
+msgid ""
+"/usr/include/sys/proc.h:\n"
+"struct thread {\n"
+" ...\n"
+" struct proc *td_proc;\n"
+" ...\n"
+"};\n"
+"struct proc {\n"
+" ...\n"
+" struct ucred *p_ucred;\n"
+" ...\n"
+"};\n"
+"/usr/include/sys/ucred.h\n"
+"struct ucred {\n"
+" ...\n"
+" struct prison *cr_prison;\n"
+" ...\n"
+"};\n"
+msgstr ""
+"/usr/include/sys/proc.h:\n"
+"struct thread {\n"
+" ...\n"
+" struct proc *td_proc;\n"
+" ...\n"
+"};\n"
+"struct proc {\n"
+" ...\n"
+" struct ucred *p_ucred;\n"
+" ...\n"
+"};\n"
+"/usr/include/sys/ucred.h\n"
+"struct ucred {\n"
+" ...\n"
+" struct prison *cr_prison;\n"
+" ...\n"
+"};\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:281
+msgid ""
+"In [.filename]#kern_jail.c#, the function `jail()` then calls function "
+"`jail_attach()` with a given `jid`. And `jail_attach()` calls function "
+"`change_root()` to change the root directory of the calling process. The "
+"`jail_attach()` then creates a new `ucred` structure, and attaches the newly "
+"created `ucred` structure to the calling process after it has successfully "
+"attached the `prison` structure to the `ucred` structure. From then on, the "
+"calling process is recognized as jailed. When the kernel routine `jailed()` "
+"is called in the kernel with the newly created `ucred` structure as its "
+"argument, it returns 1 to tell that the credential is connected with a jail. "
+"The public ancestor process of all the process forked within the jail, is "
+"the process which runs man:jail[8], as it calls the man:jail[2] system call. "
+"When a program is executed through man:execve[2], it inherits the jailed "
+"property of its parent's `ucred` structure, therefore it has a jailed "
+"`ucred` structure."
+msgstr ""
+"В файле [.filename]#kern_jail.c# функция `jail()` вызывает функцию "
+"`jail_attach()` с заданным `jid`. Затем `jail_attach()` вызывает функцию "
+"`change_root()` для изменения корневого каталога вызывающего процесса. "
+"Функция `jail_attach()` создает новую структуру `ucred` и присоединяет её к "
+"вызывающему процессу после успешного присоединения структуры `prison` к "
+"структуре `ucred`. С этого момента вызывающий процесс считается находящимся "
+"в клетке. Когда в ядре вызывается функция `jailed()` с вновь созданной "
+"структурой `ucred` в качестве аргумента, она возвращает 1, указывая, что "
+"учётные данные связаны с клеткой. Общим родительским процессом для всех "
+"процессов, созданных внутри клетки, является процесс, запускающий man:jail[8]"
+", так как он вызывает системный вызов man:jail[2]. При выполнении программы "
+"через man:execve[2] она наследует свойство клетки из структуры `ucred` "
+"родительского процесса, следовательно, у нее структура `ucred` тоже со "
+"свойством клетки."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:296
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c\n"
+"int\n"
+"jail(struct thread *td, struct jail_args *uap)\n"
+"{\n"
+"...\n"
+" struct jail_attach_args jaa;\n"
+"...\n"
+" error = jail_attach(td, &jaa);\n"
+" if (error)\n"
+" goto e_dropprref;\n"
+"...\n"
+"}\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c\n"
+"int\n"
+"jail(struct thread *td, struct jail_args *uap)\n"
+"{\n"
+"...\n"
+" struct jail_attach_args jaa;\n"
+"...\n"
+" error = jail_attach(td, &jaa);\n"
+" if (error)\n"
+" goto e_dropprref;\n"
+"...\n"
+"}\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:314
+#, no-wrap
+msgid ""
+"int\n"
+"jail_attach(struct thread *td, struct jail_attach_args *uap)\n"
+"{\n"
+" struct proc *p;\n"
+" struct ucred *newcred, *oldcred;\n"
+" struct prison *pr;\n"
+"...\n"
+" p = td->td_proc;\n"
+"...\n"
+" pr = prison_find(uap->jid);\n"
+"...\n"
+" change_root(pr->pr_root, td);\n"
+"...\n"
+" newcred->cr_prison = pr;\n"
+" p->p_ucred = newcred;\n"
+"...\n"
+"}\n"
+msgstr ""
+"int\n"
+"jail_attach(struct thread *td, struct jail_attach_args *uap)\n"
+"{\n"
+" struct proc *p;\n"
+" struct ucred *newcred, *oldcred;\n"
+" struct prison *pr;\n"
+"...\n"
+" p = td->td_proc;\n"
+"...\n"
+" pr = prison_find(uap->jid);\n"
+"...\n"
+" change_root(pr->pr_root, td);\n"
+"...\n"
+" newcred->cr_prison = pr;\n"
+" p->p_ucred = newcred;\n"
+"...\n"
+"}\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:317
+msgid ""
+"When a process is forked from its parent process, the man:fork[2] system "
+"call uses `crhold()` to maintain the credential for the newly forked "
+"process. It inherently keep the newly forked child's credential consistent "
+"with its parent, so the child process is also jailed."
+msgstr ""
+"Когда процесс создается из родительского процесса, системный вызов "
+"man:fork[2] использует `crhold()` для поддержания учетных данных нового "
+"процесса. Это автоматически сохраняет учетные данные нового дочернего "
+"процесса согласованными с родительским, поэтому дочерний процесс также "
+"остается в клетке."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:324
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_fork.c:\n"
+"p2->p_ucred = crhold(td->td_ucred);\n"
+"...\n"
+"td2->td_ucred = crhold(p2->p_ucred);\n"
+msgstr ""
+"/usr/src/sys/kern/kern_fork.c:\n"
+"p2->p_ucred = crhold(td->td_ucred);\n"
+"...\n"
+"td2->td_ucred = crhold(p2->p_ucred);\n"
+
+#. type: Title ==
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:327
+#, no-wrap
+msgid "Restrictions"
+msgstr "Ограничения"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:330
+msgid ""
+"Throughout the kernel there are access restrictions relating to jailed "
+"processes. Usually, these restrictions only check whether the process is "
+"jailed, and if so, returns an error. For example:"
+msgstr ""
+"В ядре существуют ограничения доступа, связанные с процессами в клетках. "
+"Обычно эти ограничения просто проверяют, находится ли процесс в клетке, и "
+"если да, возвращают ошибку. Например:"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:335
+#, no-wrap
+msgid ""
+"if (jailed(td->td_ucred))\n"
+" return (EPERM);\n"
+msgstr ""
+"if (jailed(td->td_ucred))\n"
+" return (EPERM);\n"
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:337
+#, no-wrap
+msgid "SysV IPC"
+msgstr "SysV IPC"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:340
+msgid ""
+"System V IPC is based on messages. Processes can send each other these "
+"messages which tell them how to act. The functions which deal with messages "
+"are: man:msgctl[3], man:msgget[3], man:msgsnd[3] and man:msgrcv[3]. Earlier, "
+"I mentioned that there were certain sysctls you could turn on or off in "
+"order to affect the behavior of jail. One of these sysctls was "
+"`security.jail.sysvipc_allowed`. By default, this sysctl is set to 0. If it "
+"were set to 1, it would defeat the whole purpose of having a jail; "
+"privileged users from the jail would be able to affect processes outside the "
+"jailed environment. The difference between a message and a signal is that "
+"the message only consists of the signal number."
+msgstr ""
+"System V IPC основан на сообщениях. Процессы могут отправлять друг другу эти "
+"сообщения, которые указывают им, как действовать. Функции, работающие с "
+"сообщениями: man:msgctl[3], man:msgget[3], man:msgsnd[3] и man:msgrcv[3]. "
+"Ранее я упоминал, что существуют определённые sysctl, которые можно включать "
+"или выключать для изменения поведения клетки. Один из таких sysctl — "
+"`security.jail.sysvipc_allowed`. По умолчанию этот sysctl установлен в 0. "
+"Если бы он был установлен в 1, это бы свело на нет весь смысл клетки: "
+"привилегированные пользователи внутри клетки смогли бы влиять на процессы за "
+"её пределами. Разница между сообщением и сигналом заключается в том, что "
+"сообщение состоит только из номера сигнала."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:342
+msgid "[.filename]#/usr/src/sys/kern/sysv_msg.c#:"
+msgstr "[.filename]#/usr/src/sys/kern/sysv_msg.c#:"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:344
+msgid ""
+"`msgget(key, msgflg)`: `msgget` returns (and possibly creates) a message "
+"descriptor that designates a message queue for use in other functions."
+msgstr ""
+"`msgget(key, msgflg)`: `msgget` возвращает (и, возможно, создаёт) дескриптор "
+"сообщения, который обозначает очередь сообщений для использования в других "
+"функциях."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:345
+msgid ""
+"`msgctl(msgid, cmd, buf)`: Using this function, a process can query the "
+"status of a message descriptor."
+msgstr ""
+"`msgctl(msgid, cmd, buf)`: С помощью этой функции процесс может запросить "
+"статус дескриптора сообщения."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:346
+msgid ""
+"`msgsnd(msgid, msgp, msgsz, msgflg)`: `msgsnd` sends a message to a process."
+msgstr ""
+"`msgsnd(msgid, msgp, msgsz, msgflg)`: `msgsnd` отправляет сообщение процессу."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:347
+msgid ""
+"`msgrcv(msgid, msgp, msgsz, msgtyp, msgflg)`: a process receives messages "
+"using this function"
+msgstr ""
+"`msgrcv(msgid, msgp, msgsz, msgtyp, msgflg)`: процесс получает сообщения с "
+"помощью этой функции"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:349
+msgid ""
+"In each of the system calls corresponding to these functions, there is this "
+"conditional:"
+msgstr ""
+"В каждом из системных вызовов, соответствующих этим функциям, присутствует "
+"следующее условие:"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:355
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/sysv_msg.c:\n"
+"if (!jail_sysvipc_allowed && jailed(td->td_ucred))\n"
+" return (ENOSYS);\n"
+msgstr ""
+"/usr/src/sys/kern/sysv_msg.c:\n"
+"if (!jail_sysvipc_allowed && jailed(td->td_ucred))\n"
+" return (ENOSYS);\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:358
+msgid ""
+"Semaphore system calls allow processes to synchronize execution by doing a "
+"set of operations atomically on a set of semaphores. Basically semaphores "
+"provide another way for processes lock resources. However, process waiting "
+"on a semaphore, that is being used, will sleep until the resources are "
+"relinquished. The following semaphore system calls are blocked inside a "
+"jail: man:semget[2], man:semctl[2] and man:semop[2]."
+msgstr ""
+"Системные вызовы семафоров позволяют процессам синхронизировать выполнение, "
+"атомарно выполняя набор операций над набором семафоров. По сути, семафоры "
+"предоставляют ещё один способ для процессов блокировать ресурсы. Однако "
+"процесс, ожидающий семафор, который уже используется, будет находиться в "
+"состоянии сна до тех пор, пока ресурсы не будут освобождены. Следующие "
+"системные вызовы семафоров блокируются внутри клетки: man:semget[2], "
+"man:semctl[2] и man:semop[2]."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:360
+msgid "[.filename]#/usr/src/sys/kern/sysv_sem.c#:"
+msgstr "[.filename]#/usr/src/sys/kern/sysv_sem.c#:"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:362
+msgid ""
+"`semctl(semid, semnum, cmd, ...)`: `semctl` does the specified `cmd` on the "
+"semaphore queue indicated by `semid`."
+msgstr ""
+"`semctl(semid, semnum, cmd, ...)`: `semctl` выполняет указанную команду `cmd`"
+" для очереди семафоров, указанной в `semid`."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:363
+msgid ""
+"`semget(key, nsems, flag)`: `semget` creates an array of semaphores, "
+"corresponding to `key`."
+msgstr ""
+"`semget(key, nsems, flag)`: `semget` создает массив семафоров, "
+"соответствующих `key`."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:365
+msgid "`key and flag take on the same meaning as they do in msgget.`"
+msgstr "`key и flag имеют то же значение, как и в msgget.`"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:366
+msgid ""
+"`semop(semid, array, nops)`: `semop` performs a group of operations "
+"indicated by `array`, to the set of semaphores identified by `semid`."
+msgstr ""
+"`semop(semid, array, nops)`: `semop` выполняет набор операций, указанных в "
+"`array`, для набора семафоров, идентифицируемых `semid`."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:368
+msgid ""
+"System V IPC allows for processes to share memory. Processes can communicate "
+"directly with each other by sharing parts of their virtual address space and "
+"then reading and writing data stored in the shared memory. These system "
+"calls are blocked within a jailed environment: man:shmdt[2], man:shmat[2], "
+"man:shmctl[2] and man:shmget[2]."
+msgstr ""
+"Система IPC System V позволяет процессам использовать общую память. Процессы "
+"могут взаимодействовать напрямую друг с другом, разделяя части своего "
+"виртуального адресного пространства и затем читая и записывая данные в общей "
+"памяти. Эти системные вызовы заблокированы в среде _клетки_: man:shmdt[2], "
+"man:shmat[2], man:shmctl[2] и man:shmget[2]."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:370
+msgid "[.filename]#/usr/src/sys/kern/sysv_shm.c#:"
+msgstr "[.filename]#/usr/src/sys/kern/sysv_shm.c#:"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:372
+msgid ""
+"`shmctl(shmid, cmd, buf)`: `shmctl` does various control operations on the "
+"shared memory region identified by `shmid`."
+msgstr ""
+"`shmctl(shmid, cmd, buf)`: `shmctl` выполняет различные управляющие операции "
+"над областью разделяемой памяти, идентифицируемой `shmid`."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:373
+msgid ""
+"`shmget(key, size, flag)`: `shmget` accesses or creates a shared memory "
+"region of `size` bytes."
+msgstr ""
+"`shmget(key, size, flag)`: `shmget` обращается к существующей или создает "
+"новую область разделяемой памяти размером `size` байт."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:374
+msgid ""
+"`shmat(shmid, addr, flag)`: `shmat` attaches a shared memory region "
+"identified by `shmid` to the address space of a process."
+msgstr ""
+"`shmat(shmid, addr, flag)`: `shmat` присоединяет область разделяемой памяти, "
+"идентифицируемую `shmid`, к адресному пространству процесса."
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:375
+msgid ""
+"`shmdt(addr)`: `shmdt` detaches the shared memory region previously attached "
+"at `addr`."
+msgstr ""
+"`shmdt(addr)`: `shmdt` отсоединяет ранее присоединенную область разделяемой "
+"памяти по адресу `addr`."
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:376
+#, no-wrap
+msgid "Sockets"
+msgstr "Сокеты"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:379
+msgid ""
+"Jail treats the man:socket[2] system call and related lower-level socket "
+"functions in a special manner. In order to determine whether a certain "
+"socket is allowed to be created, it first checks to see if the sysctl "
+"`security.jail.socket_unixiproute_only` is set. If set, sockets are only "
+"allowed to be created if the family specified is either `PF_LOCAL`, "
+"`PF_INET` or `PF_ROUTE`. Otherwise, it returns an error."
+msgstr ""
+"Клетка обрабатывает системный вызов man:socket[2] и связанные низкоуровневые "
+"функции сокетов особым образом. Для определения, разрешено ли создание "
+"определённого сокета, сначала проверяется значение sysctl `security.jail."
+"socket_unixiproute_only`. Если оно установлено, сокеты разрешено создавать "
+"только в случае, если указанное семейство равно `PF_LOCAL`, `PF_INET` или "
+"`PF_ROUTE`. В противном случае возвращается ошибка."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:397
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/uipc_socket.c:\n"
+"int\n"
+"socreate(int dom, struct socket **aso, int type, int proto,\n"
+" struct ucred *cred, struct thread *td)\n"
+"{\n"
+" struct protosw *prp;\n"
+"...\n"
+" if (jailed(cred) && jail_socket_unixiproute_only &&\n"
+" prp->pr_domain->dom_family != PF_LOCAL &&\n"
+" prp->pr_domain->dom_family != PF_INET &&\n"
+" prp->pr_domain->dom_family != PF_ROUTE) {\n"
+" return (EPROTONOSUPPORT);\n"
+" }\n"
+"...\n"
+"}\n"
+msgstr ""
+"/usr/src/sys/kern/uipc_socket.c:\n"
+"int\n"
+"socreate(int dom, struct socket **aso, int type, int proto,\n"
+" struct ucred *cred, struct thread *td)\n"
+"{\n"
+" struct protosw *prp;\n"
+"...\n"
+" if (jailed(cred) && jail_socket_unixiproute_only &&\n"
+" prp->pr_domain->dom_family != PF_LOCAL &&\n"
+" prp->pr_domain->dom_family != PF_INET &&\n"
+" prp->pr_domain->dom_family != PF_ROUTE) {\n"
+" return (EPROTONOSUPPORT);\n"
+" }\n"
+"...\n"
+"}\n"
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:399
+#, no-wrap
+msgid "Berkeley Packet Filter"
+msgstr "Berkeley Packet Filter"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:402
+msgid ""
+"The Berkeley Packet Filter provides a raw interface to data link layers in a "
+"protocol independent fashion. BPF is now controlled by the man:devfs[8] "
+"whether it can be used in a jailed environment."
+msgstr ""
+"Берклиевский фильтр пакетов (BPF) предоставляет низкоуровневый интерфейс к "
+"канальному уровню, независимый от протокола. В настоящее время BPF "
+"управляется через man:devfs[8], который определяет возможность его "
+"использования в клетке."
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:403
+#, no-wrap
+msgid "Protocols"
+msgstr "Протоколы"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:406
+msgid ""
+"There are certain protocols which are very common, such as TCP, UDP, IP and "
+"ICMP. IP and ICMP are on the same level: the network layer 2. There are "
+"certain precautions which are taken in order to prevent a jailed process "
+"from binding a protocol to a certain address only if the `nam` parameter is "
+"set. `nam` is a pointer to a `sockaddr` structure, which describes the "
+"address on which to bind the service. A more exact definition is that "
+"`sockaddr` \"may be used as a template for referring to the identifying tag "
+"and length of each address\". In the function `in_pcbbind_setup()`, `sin` is "
+"a pointer to a `sockaddr_in` structure, which contains the port, address, "
+"length and domain family of the socket which is to be bound. Basically, this "
+"disallows any processes from jail to be able to specify the address that "
+"does not belong to the jail in which the calling process exists."
+msgstr ""
+"Существуют определенные протоколы, которые очень распространены, такие как "
+"TCP, UDP, IP и ICMP. IP и ICMP находятся на одном уровне: сетевом уровне 2. "
+"Принимаются определенные меры предосторожности, чтобы предотвратить привязку "
+"протокола к определенному адресу процессом в клетке, только если установлен "
+"параметр `nam`. `nam` является указателем на структуру `sockaddr`, которая "
+"описывает адрес, к которому привязывается служба. Более точное определение "
+"заключается в том, что `sockaddr` \"может использоваться как шаблон для "
+"ссылки на идентификационный тег и длину каждого адреса\". В функции "
+"`in_pcbbind_setup()`, `sin` — это указатель на структуру `sockaddr_in`, "
+"которая содержит порт, адрес, длину и семейство доменов сокета, который "
+"должен быть привязан. В основном, это запрещает любым процессам из клетки "
+"указывать адрес, который не принадлежит клетке, в которой существует "
+"вызывающий процесс."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:443
+#, no-wrap
+msgid ""
+"/usr/src/sys/netinet/in_pcb.c:\n"
+"int\n"
+"in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,\n"
+" u_short *lportp, struct ucred *cred)\n"
+"{\n"
+" ...\n"
+" struct sockaddr_in *sin;\n"
+" ...\n"
+" if (nam) {\n"
+" sin = (struct sockaddr_in *)nam;\n"
+" ...\n"
+" if (sin->sin_addr.s_addr != INADDR_ANY)\n"
+" if (prison_ip(cred, 0, &sin->sin_addr.s_addr))\n"
+" return(EINVAL);\n"
+" ...\n"
+" if (lport) {\n"
+" ...\n"
+" if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))\n"
+" return (EADDRNOTAVAIL);\n"
+" ...\n"
+" }\n"
+" }\n"
+" if (lport == 0) {\n"
+" ...\n"
+" if (laddr.s_addr != INADDR_ANY)\n"
+" if (prison_ip(cred, 0, &laddr.s_addr))\n"
+" return (EINVAL);\n"
+" ...\n"
+" }\n"
+"...\n"
+" if (prison_ip(cred, 0, &laddr.s_addr))\n"
+" return (EINVAL);\n"
+"...\n"
+"}\n"
+msgstr ""
+"/usr/src/sys/netinet/in_pcb.c:\n"
+"int\n"
+"in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,"
+"\n"
+" u_short *lportp, struct ucred *cred)\n"
+"{\n"
+" ...\n"
+" struct sockaddr_in *sin;\n"
+" ...\n"
+" if (nam) {\n"
+" sin = (struct sockaddr_in *)nam;\n"
+" ...\n"
+" if (sin->sin_addr.s_addr != INADDR_ANY)\n"
+" if (prison_ip(cred, 0, &sin->sin_addr.s_addr))\n"
+" return(EINVAL);\n"
+" ...\n"
+" if (lport) {\n"
+" ...\n"
+" if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))\n"
+" return (EADDRNOTAVAIL);\n"
+" ...\n"
+" }\n"
+" }\n"
+" if (lport == 0) {\n"
+" ...\n"
+" if (laddr.s_addr != INADDR_ANY)\n"
+" if (prison_ip(cred, 0, &laddr.s_addr))\n"
+" return (EINVAL);\n"
+" ...\n"
+" }\n"
+"...\n"
+" if (prison_ip(cred, 0, &laddr.s_addr))\n"
+" return (EINVAL);\n"
+"...\n"
+"}\n"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:446
+msgid ""
+"You might be wondering what function `prison_ip()` does. `prison_ip()` is "
+"given three arguments, a pointer to the credential(represented by `cred`), "
+"any flags, and an IP address. It returns 1 if the IP address does NOT belong "
+"to the jail or 0 otherwise. As you can see from the code, if it is indeed an "
+"IP address not belonging to the jail, the protocol is not allowed to bind to "
+"that address."
+msgstr ""
+"Вы можете задаться вопросом, какую функцию выполняет `prison_ip()`. "
+"`prison_ip()` принимает три аргумента: указатель на учетные данные ("
+"представленные как `cred`), любые флаги и IP-адрес. Она возвращает 1, если "
+"IP-адрес НЕ принадлежит клетке, и 0 в противном случае. Как видно из кода, "
+"если это действительно IP-адрес, не принадлежащий клетке, протоколу не "
+"разрешается привязываться к этому адресу."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:454
+#, no-wrap
+msgid ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"int\n"
+"prison_ip(struct ucred *cred, int flag, u_int32_t *ip)\n"
+"{\n"
+" u_int32_t tmp;\n"
+msgstr ""
+"/usr/src/sys/kern/kern_jail.c:\n"
+"int\n"
+"prison_ip(struct ucred *cred, int flag, u_int32_t *ip)\n"
+"{\n"
+" u_int32_t tmp;\n"
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:479
+#, no-wrap
+msgid ""
+" if (!jailed(cred))\n"
+" return (0);\n"
+" if (flag)\n"
+" tmp = *ip;\n"
+" else\n"
+" tmp = ntohl(*ip);\n"
+" if (tmp == INADDR_ANY) {\n"
+" if (flag)\n"
+" *ip = cred->cr_prison->pr_ip;\n"
+" else\n"
+" *ip = htonl(cred->cr_prison->pr_ip);\n"
+" return (0);\n"
+" }\n"
+" if (tmp == INADDR_LOOPBACK) {\n"
+" if (flag)\n"
+" *ip = cred->cr_prison->pr_ip;\n"
+" else\n"
+" *ip = htonl(cred->cr_prison->pr_ip);\n"
+" return (0);\n"
+" }\n"
+" if (cred->cr_prison->pr_ip != tmp)\n"
+" return (1);\n"
+" return (0);\n"
+"}\n"
+msgstr ""
+" if (!jailed(cred))\n"
+" return (0);\n"
+" if (flag)\n"
+" tmp = *ip;\n"
+" else\n"
+" tmp = ntohl(*ip);\n"
+" if (tmp == INADDR_ANY) {\n"
+" if (flag)\n"
+" *ip = cred->cr_prison->pr_ip;\n"
+" else\n"
+" *ip = htonl(cred->cr_prison->pr_ip);\n"
+" return (0);\n"
+" }\n"
+" if (tmp == INADDR_LOOPBACK) {\n"
+" if (flag)\n"
+" *ip = cred->cr_prison->pr_ip;\n"
+" else\n"
+" *ip = htonl(cred->cr_prison->pr_ip);\n"
+" return (0);\n"
+" }\n"
+" if (cred->cr_prison->pr_ip != tmp)\n"
+" return (1);\n"
+" return (0);\n"
+"}\n"
+
+#. type: Title ===
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:481
+#, no-wrap
+msgid "Filesystem"
+msgstr "Файловая система"
+
+#. type: Plain text
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:484
+msgid ""
+"Even `root` users within the jail are not allowed to unset or modify any "
+"file flags, such as immutable, append-only, and undeleteable flags, if the "
+"securelevel is greater than 0."
+msgstr ""
+"Даже пользователи с правами `root` внутри `клетки` не могут снять или "
+"изменить любые флаги файлов, такие как неизменяемый, только для добавления и "
+"неудаляемый, если уровень безопасности (`securelevel`) больше 0."
+
+#. type: delimited block . 4
+#: documentation/content/en/books/arch-handbook/jail/_index.adoc:529
+#, no-wrap
+msgid ""
+"/usr/src/sys/ufs/ufs/ufs_vnops.c:\n"
+"static int\n"
+"ufs_setattr(ap)\n"
+" ...\n"
+"{\n"
+" ...\n"
+" if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {\n"
+" if (ip->i_flags\n"
+" & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {\n"
+" error = securelevel_gt(cred, 0);\n"
+" if (error)\n"
+" return (error);\n"
+" }\n"
+" ...\n"
+" }\n"
+"}\n"
+"/usr/src/sys/kern/kern_priv.c\n"
+"int\n"
+"priv_check_cred(struct ucred *cred, int priv, int flags)\n"
+"{\n"
+" ...\n"
+" error = prison_priv_check(cred, priv);\n"
+" if (error)\n"
+" return (error);\n"
+" ...\n"
+"}\n"
+"/usr/src/sys/kern/kern_jail.c\n"
+"int\n"
+"prison_priv_check(struct ucred *cred, int priv)\n"
+"{\n"
+" ...\n"
+" switch (priv) {\n"
+" ...\n"
+" case PRIV_VFS_SYSFLAGS:\n"
+" if (jail_chflags_allowed)\n"
+" return (0);\n"
+" else\n"
+" return (EPERM);\n"
+" ...\n"
+" }\n"
+" ...\n"
+"}\n"
+msgstr ""
+"/usr/src/sys/ufs/ufs/ufs_vnops.c:\n"
+"static int\n"
+"ufs_setattr(ap)\n"
+" ...\n"
+"{\n"
+" ...\n"
+" if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {\n"
+" if (ip->i_flags\n"
+" & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {\n"
+" error = securelevel_gt(cred, 0);\n"
+" if (error)\n"
+" return (error);\n"
+" }\n"
+" ...\n"
+" }\n"
+"}\n"
+"/usr/src/sys/kern/kern_priv.c\n"
+"int\n"
+"priv_check_cred(struct ucred *cred, int priv, int flags)\n"
+"{\n"
+" ...\n"
+" error = prison_priv_check(cred, priv);\n"
+" if (error)\n"
+" return (error);\n"
+" ...\n"
+"}\n"
+"/usr/src/sys/kern/kern_jail.c\n"
+"int\n"
+"prison_priv_check(struct ucred *cred, int priv)\n"
+"{\n"
+" ...\n"
+" switch (priv) {\n"
+" ...\n"
+" case PRIV_VFS_SYSFLAGS:\n"
+" if (jail_chflags_allowed)\n"
+" return (0);\n"
+" else\n"
+" return (EPERM);\n"
+" ...\n"
+" }\n"
+" ...\n"
+"}\n"