diff --git a/ru_RU.KOI8-R/books/developers-handbook/driverbasics/chapter.sgml b/ru_RU.KOI8-R/books/developers-handbook/driverbasics/chapter.sgml
new file mode 100644
index 0000000000..79bbcf89b7
--- /dev/null
+++ b/ru_RU.KOI8-R/books/developers-handbook/driverbasics/chapter.sgml
@@ -0,0 +1,409 @@
+
+
+
+ Написание драйверов устройств для FreeBSD
+
+ Эту главу написал Мюррэй Стокели (Murray Stokely) на основе множества
+ источников, включая справочную страницу intro(4), созданную Джоргом
+ Вуншем (Joerg Wunsch).
+
+
+ Введение
+
+ Эта глава является кратким введением в процесс написания драйверов
+ устройств для FreeBSD. В этом контексте термин устройство используется
+ в основном для вещей, связанных с оборудованием, относящимся к системе,
+ таких, как диски, печатающие устройства или графические дисплеи с
+ клавиатурами. Драйвер устройства является программной компонентой
+ операционной системы, управляющей некоторым устройством. Имеются также
+ так называемые псевдо-устройства, в случае которых драйвер устройства
+ эмулирует поведение устройства программно, без наличия какой-либо
+ соответствующей аппаратуры. Драйверы устройств могут быть
+ вкомпилированы в систему статически или могут загружаться по требованию
+ при помощи механизма динамического компоновщика ядра `kld'.
+
+ Большинство устройств в Unix-подобной операционной системе доступны
+ через файлы устройств (device-nodes), иногда также называемые
+ специальными файлами. В иерархии файловой системы эти файлы обычно
+ находятся в каталоге /dev. Пока система devfs
+ полностью не интегрирована во FreeBSD, каждый файл устройства должен
+ создаваться статически и вне зависимости от наличия соответствующего
+ драйвера устройста. Большинство файлов устройств в системе создаются
+ при помощи команды MAKEDEV.
+
+ Драйверы устройств могут быть условно разделены на две категории;
+ драйверы символьных и сетевых устройств.
+
+
+
+ Механизм динамического компоновщика ядра - KLD
+
+ Интерфейс kld позволяет системным администраторам динамически
+ добавлять и убирать функциональность из работающей системы. Это
+ позволяет разработчикам драйверов устройств загружать собственные
+ изменения в работающее ядро без постоянных перезагрузок для
+ тестирования изменений.
+
+ Для работы с интерфейсом kld используются следующие команды
+ администратора:
+
+
+
+
+ kldload - загружает новый модуль ядра
+
+
+
+
+
+ kldunload - выгружает модуль ядра
+
+
+
+
+
+ kldstat - выводит список загруженных в данный
+ момент модулей
+
+
+
+
+
+ Скелет модуля ядра
+
+
+/*
+ * KLD Skeleton
+ * Inspired by Andrew Reiter's Daemonnews article
+ */
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+
+/*
+ * Load handler that deals with the loading and unloading of a KLD.
+ */
+
+static int
+skel_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ uprintf("Skeleton KLD loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ uprintf("Skeleton KLD unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+/* Declare this module to the rest of the kernel */
+
+DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);
+
+
+
+ Makefile
+
+ Во FreeBSD имеются заготовки для включения в make-файлы, которые
+ вы можете использовать для быстрой компиляции собственных дополнений
+ к ядру.
+
+
+SRCS=skeleton.c
+KMOD=skeleton
+
+.include <bsd.kmod.mk>
+
+
+ Простой запуск команды make с этим make-файлом
+ приведет к созданию файла skeleton.ko, который
+ можно загрузить в вашу систему, набрав:
+
+
+&prompt.root kldload -v ./skeleton.ko
+
+
+
+
+
+
+ Обращение к драйверу устройства
+
+ Unix дает некоторый общий набор системных вызовов для использования
+ в пользовательских приложениях. Когда пользователь обращается к
+ файлу устройства, высокие уровни ядра перенаправляют эти обращения к
+ соответствующему драйверу устройства. Скрипт
+ /dev/MAKEDEV создает большинство файлов устройств в
+ вашей системе, однако если вы ведете разработку своего собственного
+ драйвера, то может появиться необходимость в создании собственных
+ файлов устройств при помощи команды mknod.
+
+
+ Создание статических файлов устройств
+
+ Для создания файла устройства команде mknod
+ требуется указать четыре аргумента. Вы должны указать имя этого
+ файла устройства, тип устройства, старшее число устройства и младшее
+ число устройства.
+
+
+
+ Динамические файлы устройств
+
+ Файловая система устройств, devfs, предоставляет доступ к
+ пространству имен устройств ядра из глобального пространства имен
+ файловой системы. Это устраняет потенциальную проблемы наличия
+ драйвера без статического файла устройства или файла устройства без
+ установленного драйвера устройства. Devfs все еще находится в
+ разработке, однако она уже достаточно хорошо работает.
+
+
+
+
+ Символьные устройства
+
+ Драйвер символьного устройства передает данные непосредственно в
+ или из процесса пользователя. Это самый распространенный тип драйвера
+ устройства и в дереве исходных текстов имеется достаточно простых
+ примеров таких драйверов.
+
+ В этом простом примере псевдо-устройство запоминает какие угодно
+ значения, которые вы в него записываете, и затем может выдавать их
+ назад при чтении из этого устройства.
+
+
+/*
+ * Simple `echo' pseudo-device KLD
+ *
+ * Murray Stokely
+ */
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+
+#define BUFFERSIZE 256
+
+/* Function prototypes */
+d_open_t echo_open;
+d_close_t echo_close;
+d_read_t echo_read;
+d_write_t echo_write;
+
+/* Character device entry points */
+static struct cdevsw echo_cdevsw = {
+ echo_open,
+ echo_close,
+ echo_read,
+ echo_write,
+ noioctl,
+ nopoll,
+ nommap,
+ nostrategy,
+ "echo",
+ 33, /* reserved for lkms - /usr/src/sys/conf/majors */
+ nodump,
+ nopsize,
+ D_TTY,
+ -1
+};
+
+typedef struct s_echo {
+ char msg[BUFFERSIZE];
+ int len;
+} t_echo;
+
+/* vars */
+static dev_t sdev;
+static int len;
+static int count;
+static t_echo *echomsg;
+
+MALLOC_DECLARE(M_ECHOBUF);
+MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
+
+/*
+ * This function acts is called by the kld[un]load(2) system calls to
+ * determine what actions to take when a module is loaded or unloaded.
+ */
+
+static int
+echo_loader(struct module *m, int what, void *arg)
+{
+ int err = 0;
+
+ switch (what) {
+ case MOD_LOAD: /* kldload */
+ sdev = make_dev(&echo_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "echo");
+ /* kmalloc memory for use by this driver */
+ /* malloc(256,M_ECHOBUF,M_WAITOK); */
+ MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
+ printf("Echo device loaded.\n");
+ break;
+ case MOD_UNLOAD:
+ destroy_dev(sdev);
+ FREE(echomsg,M_ECHOBUF);
+ printf("Echo device unloaded.\n");
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ return(err);
+}
+
+int
+echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+ int err = 0;
+
+ uprintf("Opened device \"echo\" successfully.\n");
+ return(err);
+}
+
+int
+echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
+{
+ uprintf("Closing device \"echo.\"\n");
+ return(0);
+}
+
+/*
+ * The read function just takes the buf that was saved via
+ * echo_write() and returns it to userland for accessing.
+ * uio(9)
+ */
+
+int
+echo_read(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+ int amt;
+
+ /* How big is this read operation? Either as big as the user wants,
+ or as big as the remaining data */
+ amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
+ if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
+ uprintf("uiomove failed!\n");
+ }
+
+ return err;
+}
+
+/*
+ * echo_write takes in a character string and saves it
+ * to buf for later accessing.
+ */
+
+int
+echo_write(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ /* Copy the string in from user memory to kernel memory */
+ err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));
+
+ /* Now we need to null terminate */
+ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
+ /* Record the length */
+ echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);
+
+ if (err != 0) {
+ uprintf("Write failed: bad address!\n");
+ }
+
+ count++;
+ return(err);
+}
+
+DEV_MODULE(echo,echo_loader,NULL);
+
+
+ Перед тем, как устанавливать этот драйвер, в вашей файловой системе
+ вам нужно создать файл устройства при помощи команды, подобной
+ следующей:
+
+
+&prompt.root mknod /dev/echo c 33 0
+
+
+ Когда этот драйвер загружен, вы можете выполнять следующие
+ действия:
+
+
+&prompt.root echo -n "Test Data" > /dev/echo
+&prompt.root cat /dev/echo
+Test Data
+
+
+ Об устройствах, обслуживающих реальное оборудование, рассказывается
+ в следующей главе..
+
+ Дополнительные источники информации
+
+
+ Учебник
+ по программированию механизма динамического компоновщика ядра
+ (KLD) - Daemonnews
+ Октябрь 2000
+
+
+
+
+ Как
+ писать драйверы ядра в парадигме NEWBUS - Daemonnews Июль 2000
+
+
+
+
+
+
+
+ Сетевые драйверы
+
+ В случае драйверов сетевых устройств файлы устройств для доступа к
+ ним не используются. Их выбор основан на другом механизме, работающем
+ в ядре, и не использующем вызов open(); об использование сетевых
+ устройств в общем случае рассказано в описании системного вызова
+ socket(2).
+
+ Почитайте справочную информацию о вызове ifnet(), устройстве
+ loopback, почитайте драйверы Билла Пола (Bill Paul), и так
+ далее..
+
+
\ No newline at end of file
diff --git a/ru_RU.KOI8-R/books/developers-handbook/locking/chapter.sgml b/ru_RU.KOI8-R/books/developers-handbook/locking/chapter.sgml
new file mode 100644
index 0000000000..b70a6e7de8
--- /dev/null
+++ b/ru_RU.KOI8-R/books/developers-handbook/locking/chapter.sgml
@@ -0,0 +1,339 @@
+
+
+
+ Замечания по блокировке
+
+ Эта глава поддерживается проектом FreeBSD SMP Next
+ Generation Project
+ freebsd-smp@FreeBSD.org.
+
+ Этот документ описывает механизм блокировки, используемый в ядре
+ FreeBSD для обеспечения эффективной поддержки нескольких процессоров в
+ ядре. Блокировку можно рассматривать с нескольких точек зрения.
+ Структуры данных могут быть защищены с помощью блокировок mutex или
+ &man.lockmgr.9;. Несколько переменных защищены просто в силу атомарности
+ используемых для доступа к ним операций.
+
+
+ Мьютексы
+
+ Мьютекс (mutex) - это просто блокировка, используемая для
+ реализации гарантированной исключительности. В частности, в каждый
+ момент времени мьютексом может владеть только один объект. Если
+ какой-то объект хочет получить мьютекс, который уже кто-то занял, он
+ должен дождаться момента его освобождения. В ядре FreeBSD владельцами
+ мьютексов являются процессы.
+
+ Мьютексы могут быть затребованы рекурсивно, но предполагается, что
+ они занимаются на короткое время. В частности, владельцу мьютекса
+ нельзя выдерживать паузу. Если вам нужно выполнить блокировку на время
+ паузы, используйте блокировку через &man.lockmgr.9;.
+
+ Каждый мьютекс имеет несколько представляющих интерес
+ характеристик:
+
+
+
+ Имя переменной
+
+ Имя переменной struct mtx в исходных текстах
+ ядра.
+
+
+
+
+ Логическое имя
+
+ Имя мьютекса, назначенное ему через
+ mtx_init. Это имя выводится в сообщениях
+ трассировки KTR и диагностических предупреждающих и ошибочных
+ сообщениях и используется для идентификации мьютексов в
+ отладочном коде.
+
+
+
+
+ Тип
+
+ Тип мьютекса в терминах флагов MTX_*.
+ Значение каждого флага связано с его смыслом так, как это описано
+ в &man.mutex.9;.
+
+
+
+ MTX_DEF
+
+ Sleep-мьютекс
+
+
+
+
+ MTX_SPIN
+
+ Spin-мьютекс
+
+
+
+
+ MTX_COLD
+
+ Этот мьютекс инициализируется очень рано. Поэтому он
+ должен быть объявлен через функции
+ MUTEX_DECLARE, а флаг
+ MTX_COLD должен быть передан в функцию
+ mtx_init.
+
+
+
+
+ MTX_TOPHALF
+
+ Этот spin-мьютекс не запрещает прерывания.
+
+
+
+
+ MTX_NORECURSE
+
+ Этот мьютекс не разрешается блокировать
+ рекурсивно.
+
+
+
+
+
+
+
+ Защиты
+
+ Список структур данных или членов структур данных, которые
+ защищает этот мьютекс. Для членов структур данных иям будет в
+ форме
+
+
+
+
+
+ Зависимые функции
+
+ Функции, которые можно вызвать, если этот мьютекс
+ занят.
+
+
+
+
+
+ Список мьютексов
+
+
+
+
+ Имя переменной
+ Логическое имя
+ Тип
+ Защиты
+ Зависимые функции
+
+
+
+
+
+
+ sched_lock
+ sched lock
+
+ MTX_SPIN |
+ MTX_COLD
+
+
+ _gmonparam,
+ cnt.v_swtch,
+ cp_time,
+ curpriority,
+ P_PROFIL XXX,
+ P_INMEM,
+ P_SINTR,
+ P_TIMEOUT,
+ P_SWAPINREQ XXX,
+ P_INMEN XXX),
+ p_prof/,
+ p_ru/,
+ statclock),
+ pscnt,
+ slpque,
+ itqueuebits,
+ itqueues,
+ rtqueuebits,
+ rtqueues,
+ queuebits,
+ queues,
+ idqueuebits,
+ idqueues,
+ switchtime,
+
+
+ setrunqueue,
+ remrunqueue,
+ mi_switch,
+ chooseproc,
+ schedclock,
+ resetpriority,
+ updatepri,
+ maybe_resched,
+ cpu_switch,
+ cpu_throw
+
+
+
+
+
+ vm86pcb_lock
+ vm86pcb lock
+
+ MTX_DEF |
+ MTX_COLD
+
+
+ vm86pcb
+
+
+ vm86_bioscall
+
+
+
+
+
+ Giant
+ Giant
+
+ MTX_DEF |
+ MTX_COLD
+
+ nearly everything
+ lots
+
+
+
+
+ callout_lock
+ callout lock
+
+ MTX_SPIN
+
+
+ callfree,
+ callwheel,
+ nextsoftcheck,
+ softticks,
+ ticks
+
+
+
+
+
+
+
+
+
+
+ Блокировки менеджера блокировок
+
+ Блокировки, которые даются через интерфейс &man.lockmgr.9;,
+ являются блокировками менеджера блокировок. Эти блокировки являются
+ блокировками на чтение/запись и ими могут владеть процессы в состоянии
+ ожидания.
+
+
+ Список блокировок &man.lockmgr.9;
+
+
+
+
+ Имя переменной
+ Защиты
+
+
+
+
+ allproc_lock
+
+ allproc
+ zombproc
+ pidhashtbl
+ nextpid
+
+ proctree_lock
+
+
+
+
+
+
+
+
+
+ Атомарно защищенные переменные
+
+ Переменной, защищенной атомарно, является особая переменная,
+ которая не защищается явной блокировкой. Вместо этого для доступа к
+ данным переменных используются специальные атомарные операции, как
+ описано в &man.atomic.9;. Лишь несколько переменных используются таким
+ образом, хотя другие примитивы синхронизации, такие как мьютексы,
+ реализованы с атомарно защищенными переменными.
+
+
+
+ astpending
+
+
+
+
+
+
+
+
diff --git a/ru_RU.KOI8-R/books/developers-handbook/pci/chapter.sgml b/ru_RU.KOI8-R/books/developers-handbook/pci/chapter.sgml
new file mode 100644
index 0000000000..e380721dac
--- /dev/null
+++ b/ru_RU.KOI8-R/books/developers-handbook/pci/chapter.sgml
@@ -0,0 +1,221 @@
+
+
+
+ Устройства PCI
+
+ Эта глава посвящена механизмам FreeBSD по написанию драйверов
+ устройств, работающих на шине PCI.
+
+ Обнаружение и подключение
+
+ Здесь находится информация о том, как код шины PCI проходит по
+ неподключенным устройствам и распознает возможность загруженного драйвера
+ kld выполнить подключение к какому-либо из них.
+
+
+/*
+ * Simple KLD to play with the PCI functions.
+ *
+ * Murray Stokely
+ */
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h> /* uprintf */
+#include <sys/errno.h>
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
+
+#include <pci/pcivar.h> /* For get_pci macros! */
+
+/* Function prototypes */
+d_open_t mypci_open;
+d_close_t mypci_close;
+d_read_t mypci_read;
+d_write_t mypci_write;
+
+/* Character device entry points */
+
+static struct cdevsw mypci_cdevsw = {
+ mypci_open,
+ mypci_close,
+ mypci_read,
+ mypci_write,
+ noioctl,
+ nopoll,
+ nommap,
+ nostrategy,
+ "mypci",
+ 36, /* reserved for lkms - /usr/src/sys/conf/majors */
+ nodump,
+ nopsize,
+ D_TTY,
+ -1
+};
+
+/* vars */
+static dev_t sdev;
+
+/* We're more interested in probe/attach than with
+ open/close/read/write at this point */
+
+int
+mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
+{
+ int err = 0;
+
+ uprintf("Opened device \"mypci\" successfully.\n");
+ return(err);
+}
+
+int
+mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
+{
+ int err=0;
+
+ uprintf("Closing device \"mypci.\"\n");
+ return(err);
+}
+
+int
+mypci_read(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ uprintf("mypci read!\n");
+ return err;
+}
+
+int
+mypci_write(dev_t dev, struct uio *uio, int ioflag)
+{
+ int err = 0;
+
+ uprintf("mypci write!\n");
+ return(err);
+}
+
+/* PCI Support Functions */
+
+/*
+ * Return identification string if this is device is ours.
+ */
+static int
+mypci_probe(device_t dev)
+{
+ uprintf("MyPCI Probe\n"
+ "Vendor ID : 0x%x\n"
+ "Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));
+
+ if (pci_get_vendor(dev) == 0x11c1) {
+ uprintf("We've got the Winmodem, probe successful!\n");
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+/* Attach function is only called if the probe is successful */
+
+static int
+mypci_attach(device_t dev)
+{
+ uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));
+ sdev = make_dev(&mypci_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "mypci");
+ uprintf("Mypci device loaded.\n");
+ return ENXIO;
+}
+
+/* Detach device. */
+
+static int
+mypci_detach(device_t dev)
+{
+ uprintf("Mypci detach!\n");
+ return 0;
+}
+
+/* Called during system shutdown after sync. */
+
+static int
+mypci_shutdown(device_t dev)
+{
+ uprintf("Mypci shutdown!\n");
+ return 0;
+}
+
+/*
+ * Device suspend routine.
+ */
+static int
+mypci_suspend(device_t dev)
+{
+ uprintf("Mypci suspend!\n");
+ return 0;
+}
+
+/*
+ * Device resume routine.
+ */
+
+static int
+mypci_resume(device_t dev)
+{
+ uprintf("Mypci resume!\n");
+ return 0;
+}
+
+static device_method_t mypci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mypci_probe),
+ DEVMETHOD(device_attach, mypci_attach),
+ DEVMETHOD(device_detach, mypci_detach),
+ DEVMETHOD(device_shutdown, mypci_shutdown),
+ DEVMETHOD(device_suspend, mypci_suspend),
+ DEVMETHOD(device_resume, mypci_resume),
+
+ { 0, 0 }
+};
+
+static driver_t mypci_driver = {
+ "mypci",
+ mypci_methods,
+ 0,
+ /* sizeof(struct mypci_softc), */
+};
+
+static devclass_t mypci_devclass;
+
+DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);
+
+
+ Дополнительная информация
+
+ PCI Special Interest
+ Group
+
+ PCI System Architecture, Fourth Edition by
+ Tom Shanley, et al.
+
+
+
+
\ No newline at end of file
diff --git a/ru_RU.KOI8-R/books/developers-handbook/secure/chapter.sgml b/ru_RU.KOI8-R/books/developers-handbook/secure/chapter.sgml
new file mode 100644
index 0000000000..7006818a5f
--- /dev/null
+++ b/ru_RU.KOI8-R/books/developers-handbook/secure/chapter.sgml
@@ -0,0 +1,439 @@
+
+
+
+ Безопасное программирование
+
+ Эту главу написал Мюррей Стокели (Murray Stokely).
+
+
+ Обзор
+
+ Эта глава описывает некоторые из проблем обеспечения безопасности,
+ которые десятилетиями преследовали программистов Unix, а также
+ несколько новых доступных инструментов, помогающих программистам
+ избежать написания небезопасного кода.
+
+
+
+ Методология обеспечения безопасности
+
+ Написание безопасных приложений требует весьма критического и
+ пессимистического взгляда на жизнь. Приложения должны работать по
+ принципу наименьших привилегий
, при котором никакой
+ процесс не должен работать с привилегиями, превышающими минимально
+ необходимый для выполнения своих функций минимум. Ранее проверенный
+ код должен использоваться там, где только это возможно для избежания
+ общих ошибок, которые могли быть уже исправлены другими.
+
+ Одной из неприятностей в среде Unix является легкость в
+ предположении безопасности этого окружения. Приложения никогда не
+ должны верить пользовательскому вводу (во всех его формах), ресурсам
+ системы, межпроцессному взаимодействию или времени выполнения событий.
+ Процессы Unix выполняются не синхронно, так что логические операции
+ редко бывают атомарными.
+
+
+
+ Переполнения буфера
+
+ Переполнения буфера появились вместе с появление архитектуры
+ Фон-Неймана . Впервые широкую известность они
+ получили в 1988 году вместе с Интернет-червем Мурса (Moorse). К
+ сожалению, точно такая же атака повторилась и в наши дни. Из 17
+ бюллетеней безопасности CERT за 1999 год, 10 были непосредственно
+ вызваны ошибкам в программном обеспечении, связанным с переполнениями
+ буфера. Самые распространенные типы атак с использованием переполнения
+ буфера основаны на разрушении стека.
+
+ Самые современные вычислительные системы используют стек для
+ передачи аргументов процедурам и сохранения локальных переменных. Стек
+ является буфером типа LIFO (последним вошел первым вышел) в верхней
+ части области памяти процесса. Когда программа вызывает функцию,
+ создается новая "граница стека". Эта граница состоит из аргументов,
+ переданных в функцию, а также динамического количества пространства
+ локальных переменных. "Указатель стека" является регистром, хранящим
+ текущее положение вершины стека. Так как это значение постоянно
+ меняется вместе с помещением новых значений на вершину стека, многие
+ реализации также предусматривают "указатель границы", который
+ расположен около начала стека, так что локальные переменные можно легко
+ адресовать относительно этого значения. Адрес
+ возврата из функции также сохраняется в стеке, и это является причиной
+ нарушений безопасности, связанных с переполнением стека, так как
+ перезаписывание локальной переменной в функции может изменить адрес
+ возврата из этой функции, потенциально позволяя злоумышленнику
+ выполнить любой код.
+
+ Хотя атаки с переполнением стека являются замыми распространенными,
+ стек можно также перезаписать при помощи атаки, основанной на выделении
+ памяти (malloc/free) из "кучи".
+
+ Как и во многих других языках программирования, в C не выполняется
+ автоматической проверки границ в массивах или указателях. Кроме того,
+ стандартная библиотека C полна очень опасных функций.
+
+
+
+
+
+ strcpy(char *dest, const char
+ *src)
+ Может переполнить целевой буфер
+
+
+
+ strcat(char *dest, const char
+ *src)
+ Может переполнить целевой буфер
+
+
+
+ getwd(char *buf)
+ Может переполнить буфер buf
+
+
+
+ gets(char *s)
+ Может переполнить буфер s
+
+
+
+ [vf]scanf(const char *format,
+ ...)
+ Может переполнить свои аргументы.
+
+
+
+ realpath(char *path, char
+ resolved_path[])
+ Может переполнить буфер path
+
+
+
+ [v]sprintf(char *str, const char
+ *format, ...)
+ Может переполнить буфер str.
+
+
+
+
+
+
+ Пример переполнения буфера
+
+ В следующем примере кода имеется ошибка переполнения буфера,
+ предназначенная для перезаписи адреса возврата и обхода инструкции,
+ следующей непосредственно за вызовом функции. (По мотивам )
+
+
+#include stdio.h
+
+void manipulate(char *buffer) {
+ char newbuffer[80];
+ strcpy(newbuffer,buffer);
+}
+
+int main() {
+ char ch,buffer[4096];
+ int i=0;
+
+ while ((buffer[i++] = getchar()) != '\n') {};
+
+ i=1;
+ manipulate(buffer);
+ i=2;
+ printf("The value of i is : %d\n",i);
+ return 0;
+}
+
+
+ Давайте посмотрим, как будет выглядеть образ процесса, если в
+ нашу маленькую программу мы введем 160 пробелов.
+
+ [XXX figure here!]
+
+ Очевидно, что для выполнения реальных инструкций (таких, как
+ exec(/bin/sh)), может быть придуман более вредоносный ввод.
+
+
+
+ Как избежать переполнений буфера
+
+ Самым прямолинейным решением проблемы переполнения стека является
+ использование только памяти фиксированного размера и функций
+ копирования строк. Функции strncpy и
+ strncat являются частью стандартной библиотеки
+ C. Эти функции будут копировать не более указанного количества байт
+ из исходной строки в целевую. Однако у этих функций есть несколько
+ проблем. Ни одна из них не гарантирует наличие символа NUL, если
+ размер входного буфера больше, чем целевого. Параметр длины также
+ по-разному используется в strncpy и strncat, так что для
+ программистов легко запутаться в правильном использовании. Есть
+ также и значительная потеря производительности по сравнению с
+ strcpy при копировании короткой строки в большой
+ буфер, потому что strncpy заполняет символами
+ NUL пространство до указанной длины.
+
+ Для избежания этих проблем в OpenBSD была сделана другая
+ реализация копирования памяти. Функции strlcpy
+ и strlcat гарантируют, что они они всегда
+ терминируют целевую строку нулевым символом, если им будет передан
+ аргумент ненулевой длины. Более подробная информация об этом
+ находится здесь . Инструкции OpenBSD
+ strlcpy и strlcat были
+ во FreeBSD начиная с 3.5.
+
+
+ Вкомпилированная проверка границ во время выполнения
+
+ К несчастью, все еще широко используется очень большой объем
+ кода, который слепо копирует память без использования только что
+ рассмотренных функций с проверкой границ. Однако есть другое
+ решение. Существует несколько расширений к компилятору и
+ библиотекам C/C++ для выполнения контроля границ во время
+ выполнения.
+
+ Одним из таких добавлений является StackGuard, который
+ реализован как маленький патч к генератору кода gcc. Согласно
+ сайту StackGuard, http://immunix.org/stackguard.html:
+
+ "StackGuard распознает и защищает стек от атак,
+ не позволяя изменять адрес возврата в стеке. При вызове
+ функции StackGuard помещает вслед за адресом возврата
+ сигнальное слово. Если после возврата из функции оно
+ оказывается измененным, то была попытка выполнить атаку на
+ стек, и программа отвечает на это генерацией сообщения о
+ злоумышленнике в системном журнале, а затем прекращает
+ работу."
+
+
+
+ "StackGuard реализован в виде маленького патча к генератору
+ кода gcc, а именно процедур function_prolog() и
+ function_epilog(). function_prolog() усовершенствована для
+ создания пометок в стеке при начале работы функции, а
+ function_epilog() проверяет челостность пометки при возврате из
+ функции. Таким образом, любые попытки изменения адреса
+ возврата определяются до возврата из функции."
+
+
+
+ Перекомпиляция вашего приложения со StackGuard является
+ эффективным способом остановить большинство атак переполнений
+ буфера, но все же полностью это проблемы не решает.
+
+
+
+ Проверка границ во время выполнения с использованием
+ библиотек.
+
+ Механизмы на основе компилятора полностью бесполезны для
+ программного обеспечения, поставляемого в двоичном виде, которое вы
+ не можете перекомпилировать. В этих ситуациях имеется некоторое
+ количество библиотек, в которых реализованы небезопасные функции
+ библиотеки C (strcpy,
+ fscanf, getwd, и так
+ далее..), обеспечивающие невозможность записи после указателя
+ стека.
+
+
+ libsafe
+ libverify
+ libparnoia
+
+
+ К сожалению, эти защиты имеют некоторое количество недостатков.
+ Эти библиотеки могут защитить только против малого количества
+ проблем, и не могут исправить реальные проблемы. Эти защиты могут
+ не сработать, если приложение скомпилировано с параметром
+ -fomit-frame-pointer. К тому же переменные окружения LD_PRELOAD и
+ LD_LIBRARY_PATH могут быть переопределены/сняты
+ пользователем.
+
+
+
+
+
+ Проблемы с установленным битом UID
+
+ Имеется по крайней мере 6 различных идентификаторов (ID), связанных
+ с любым взятым процессом. Поэтому вы должны быть очень осторожны с
+ тем, какие права имеет ваш процесс в каждый момент времени. В
+ частности, все seteuid-приложения должны понижать свои привилегии, как
+ только в них отпадает необходимость.
+
+ ID реального пользователя может быть изменен только процессом
+ администратора. Программа login
+ устанавливает его, когда пользователь входит в систему, и он редко
+ меняется.
+
+ Эффективный ID пользователя устанавливается функциями
+ exec(), если у программы установлен бит seteuidt.
+ Приложение может выполнить вызов seteuid() в любой
+ момент для установки эффективного ID пользователя в значение реального
+ ID пользователя или сохраняемого set-user-ID. Когда эффективный ID
+ пользователя устанавливается функциями exec(), его
+ предыдущее значение сохраняется в сохраняемом set-user-ID.
+
+
+
+ Ограничение среды работы вашей программы
+
+ Традиционно используемым методом ограничения доступа к процессу
+ является использование системного вызова chroot().
+ Этот системный вызов меняет корневой каталог, относительно которого
+ определяются все остальные пути в самом процессе и всех порожденных ими
+ процессах. Для того, чтобы этот вызов был выполнен успешно, процесс
+ должен иметь право на выполнение (поиск) каталога, о котором идет речь.
+ Новая среда реально не вступит в силу, пока вы не выполните вызов
+ chdir() в вашей новой среде. Следует также
+ отметить, что процесс может с легкостью выйти из chroot-среды, если он
+ имеет привилегии администратора. Это может быть достигнуто созданием
+ файлов устройств для чтения памяти ядра, подключением отладчика к
+ процессу вне узницы и многими другими способами.
+
+ Поведение системного вызова chroot() можно
+ некоторым образом контролировать sysctl-переменной
+ kern.chroot_allow_open_directories. Когда эта переменная установлена в
+ 0, chroot() не сработает с ошибкой EPERM, если
+ есть какие-либо открытые каталоги. Если она установлена в значение по
+ умолчанию, равное 1, то chroot() не сработает с
+ ошибкой EPERM, если есть какие-либо открытые каталоги и процесс уже
+ подвергнут вызову chroot(). Для всех других
+ значений проверка открытости каталогов будет полностью опущена.
+
+
+ Функциональность джейлов (jail) во FreeBSD
+
+ Концепция джейлов (Jail) расширяет возможности
+ chroot(), ограничивая власть администратора
+ созданием настоящих `виртуальных серверов'. Как только тюремная
+ камера создана, все сетевые коммуникации должны осуществляться через
+ выделенный адрес IP, а сила "привилегий пользователя root" в этой
+ тюрьме довольно ограничена.
+
+ При работе внутри тюрьмы, любые проверки силы администратора в
+ ядре при помощи вызова suser() будут
+ оканчиваться неудачно. Однако некоторые вызовы к
+ suser() были изменены на новый интерфейс
+ suser_xxx(). Эта функция отвечает за
+ распознание и разрешение доступа к власти администратора для
+ процессов, не находящихся в неволе.
+
+ Процесс администратора внутри среды джейла имеет право:
+
+
+ Манипулировать привилегиями с помощью
+ setuid, seteuid,
+ setgid, setegid,
+ setgroups, setreuid,
+ setregid и
+ setlogin
+
+
+ Устанавливать ограничения на использование
+ ресурсов при помощи
+ setrlimit
+
+
+ Модифицировать некоторые sysctl-переменные
+ (kern.hostname)
+
+
+ chroot()
+
+ Устанавливать следующие флаги на vnode:
+ chflags,
+ fchflags
+
+
+ Устанавливать такие атрибуты vnode, как права
+ доступа к файлу, изменять его владельца, группу, размер, время
+ доступа и модификации.
+
+
+ Осуществлять привязку к привилегированному порту
+ в области портов Интернет (порты с номерами < 1024)
+
+
+
+ Jail является очень полезным инструментом
+ для запуска приложений в защищенном окружении, но есть и некоторые
+ недостатки. На текущий момент к формату
+ suser_xxx не преобразованы механизмы IPC, так
+ что такие приложения, как MySQL, не могут работать в джейле. Права
+ администратора могут имеет малую силу внутри джейла, но нет
+ способа определить, что значит "малую".
+
+
+
+ Возможности процессов POSIX.1e
+
+ Posix выпустил рабочий документ, который добавляет аудит событий,
+ списки управления доступом, тонко настраиваемые привилегии, метки
+ информации и жесткое управление доступом.
+
+ Этот документ находится в работе и находится в центре внимания
+ проекта TrustedBSD.
+ Некоторая начальная функциональность уже была добавлена во
+ FreeBSD-current (cap_set_proc(3)).
+
+
+
+
+ Доверие
+
+ Приложение никогда не должно полагать, что среда пользователя
+ безопасна. Сюда включается (но этим не ограничено): ввод пользователя,
+ сигналы, переменные среды, ресурсы, IPC, отображаемая в файл память,
+ рабочий каталог файловой системы, дескрипторы файлов, число открытых
+ файлов и прочее.
+
+ Никогда не думайте, что сможете предусмотреть все формы
+ неправильного ввода, который может дать пользователь. Вместо этого
+ ваше приложение должно осуществлять позитивную фильтрацию, пропуская
+ только конечное множество возможных вариантов ввода, которые вы
+ считаете безопасными. Неполная праверка данных была причиной многих
+ нарушений защиты, особенно CGI-скриптов на веб-сайтах. Для имен файлов
+ вам нужно уделять особое внимание путям ("../", "/"), символическим
+ ссылкам и экранирующим символам оболочки.
+
+ В perl имеется такая очень полезная вещь, как "безупречный" (taint)
+ режим, который можно использовать для запрещения скриптам использовать
+ данные, порожденные вне программы, не безопасным способом. Этот режим
+ проверяет аргументы командной строки, переменные окружения, информацию
+ локализации, результаты некоторых системных вызовов
+ (readdir(), readlink(),
+ getpwxxx() и весь файловый ввод.
+
+
+
+ Неожиданное поведение
+
+ Неожиданное поведение - это аномальное поведение, вызванное
+ непредусмотренной зависимостью от относительной последовательности
+ событий. Другими словами, программист неправильно предположил, что
+ некоторое событие всегда случается перед другим.
+
+ Некоторые из широко распространенных причин возникновения таких
+ проблем являются сигналы, проверки доступа и открытия файлов. Сигналы
+ по своей природе являются асинхронными событиями, так что по отношению
+ к ним нужно проявлять особое внимание. Проверка доступа функцией
+ access(2) с последующим вызовом
+ open(2) полностью не атомарно. Пользователи могут
+ переместить файлы в промежутке между двумя вызовами. Вместо этого
+ привилегированное приложение должно выполнить
+ seteuid(), а затем сразу вызвать
+ open(). В тех же строках приложение должно всегда
+ устанавливать явно маску прав доступа (umask) перед вызовом функции
+ open() во избежание беспорядочных вызовов
+ chmod().
+
+
\ No newline at end of file