aboutsummaryrefslogtreecommitdiff
path: root/en_US.ISO8859-1/books
diff options
context:
space:
mode:
Diffstat (limited to 'en_US.ISO8859-1/books')
-rw-r--r--en_US.ISO8859-1/books/Makefile15
-rw-r--r--en_US.ISO8859-1/books/Makefile.inc5
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/Makefile57
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/book.xml192
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/boot/chapter.xml2396
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/chapters.ent34
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml423
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/isa/chapter.xml2514
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/jail/chapter.xml794
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/kobj/chapter.xml304
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/locking/chapter.xml391
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/mac.ent111
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/mac/chapter.xml8068
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/newbus/chapter.xml415
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/pccard/chapter.xml367
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/pci/chapter.xml458
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/scsi/chapter.xml2239
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/smp/chapter.xml1153
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/sound/chapter.xml684
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/sysinit/chapter.xml210
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/usb/chapter.xml721
-rw-r--r--en_US.ISO8859-1/books/arch-handbook/vm/chapter.xml298
-rw-r--r--en_US.ISO8859-1/books/design-44bsd/Makefile16
-rw-r--r--en_US.ISO8859-1/books/design-44bsd/book.xml2721
-rw-r--r--en_US.ISO8859-1/books/dev-model/Makefile28
-rw-r--r--en_US.ISO8859-1/books/dev-model/book.xml2965
-rw-r--r--en_US.ISO8859-1/books/dev-model/chapters.ent3
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/Makefile43
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/book.xml192
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/chapters.ent33
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/introduction/chapter.xml220
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/ipv6/chapter.xml1638
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/kernelbuild/chapter.xml73
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/kerneldebug/Makefile15
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/kerneldebug/chapter.xml1075
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/l10n/chapter.xml319
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/policies/Makefile15
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/policies/chapter.xml612
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/secure/chapter.xml500
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/sockets/chapter.xml1748
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/testing/chapter.xml488
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/tools/chapter.xml2605
-rw-r--r--en_US.ISO8859-1/books/developers-handbook/x86/chapter.xml5562
-rw-r--r--en_US.ISO8859-1/books/faq/Makefile29
-rw-r--r--en_US.ISO8859-1/books/faq/book.xml6431
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/Makefile59
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/book.xml281
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/chapters.ent30
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/doc-build/chapter.xml531
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/docbook-markup/chapter.xml2761
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/editor-config/chapter.xml248
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/examples/appendix.xml161
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/manpages/chapter.xml746
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/overview/chapter.xml273
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/po-translations/chapter.xml921
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/psgml-mode/chapter.xml169
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/see-also/chapter.xml107
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/structure/chapter.xml314
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/stylesheets/chapter.xml76
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/the-website/chapter.xml285
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/tools/chapter.xml141
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/translations/chapter.xml483
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/working-copy/chapter.xml184
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/writing-style/chapter.xml607
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/xhtml-markup/chapter.xml604
-rw-r--r--en_US.ISO8859-1/books/fdp-primer/xml-primer/chapter.xml1423
-rw-r--r--en_US.ISO8859-1/books/handbook/Makefile306
-rw-r--r--en_US.ISO8859-1/books/handbook/advanced-networking/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/advanced-networking/chapter.xml5390
-rw-r--r--en_US.ISO8859-1/books/handbook/audit/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/audit/chapter.xml769
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/chapter.xml3417
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/disk-layout.eps2970
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/disk-layout.ps165
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/example-dir1.dot7
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/example-dir2.dot8
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/example-dir3.dot8
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/example-dir4.dot9
-rw-r--r--en_US.ISO8859-1/books/handbook/basics/example-dir5.dot9
-rw-r--r--en_US.ISO8859-1/books/handbook/bibliography/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/bibliography/chapter.xml606
-rw-r--r--en_US.ISO8859-1/books/handbook/book.xml324
-rw-r--r--en_US.ISO8859-1/books/handbook/boot/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/boot/chapter.xml892
-rw-r--r--en_US.ISO8859-1/books/handbook/bsdinstall/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/bsdinstall/chapter.xml3018
-rw-r--r--en_US.ISO8859-1/books/handbook/chapters.ent68
-rw-r--r--en_US.ISO8859-1/books/handbook/colophon.xml20
-rw-r--r--en_US.ISO8859-1/books/handbook/config/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/config/chapter.xml3486
-rw-r--r--en_US.ISO8859-1/books/handbook/cutting-edge/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/cutting-edge/chapter.xml1701
-rw-r--r--en_US.ISO8859-1/books/handbook/desktop/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/desktop/chapter.xml920
-rw-r--r--en_US.ISO8859-1/books/handbook/disks/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/disks/chapter.xml3694
-rw-r--r--en_US.ISO8859-1/books/handbook/dtrace/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/dtrace/chapter.xml363
-rw-r--r--en_US.ISO8859-1/books/handbook/eresources/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/eresources/chapter.xml2481
-rw-r--r--en_US.ISO8859-1/books/handbook/filesystems/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/filesystems/chapter.xml181
-rw-r--r--en_US.ISO8859-1/books/handbook/firewalls/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/firewalls/chapter.xml4250
-rw-r--r--en_US.ISO8859-1/books/handbook/geom/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/geom/chapter.xml1693
-rw-r--r--en_US.ISO8859-1/books/handbook/index.xml1
-rw-r--r--en_US.ISO8859-1/books/handbook/introduction/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/introduction/chapter.xml1162
-rw-r--r--en_US.ISO8859-1/books/handbook/jails/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/jails/chapter.xml1692
-rw-r--r--en_US.ISO8859-1/books/handbook/kernelconfig/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/kernelconfig/chapter.xml1341
-rw-r--r--en_US.ISO8859-1/books/handbook/l10n/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/l10n/chapter.xml1036
-rw-r--r--en_US.ISO8859-1/books/handbook/linuxemu/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/linuxemu/chapter.xml1247
-rw-r--r--en_US.ISO8859-1/books/handbook/mac/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/mac/chapter.xml1776
-rw-r--r--en_US.ISO8859-1/books/handbook/mail/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/mail/chapter.xml1950
-rw-r--r--en_US.ISO8859-1/books/handbook/mirrors/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/mirrors/chapter.xml505
-rw-r--r--en_US.ISO8859-1/books/handbook/multimedia/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/multimedia/chapter.xml1696
-rw-r--r--en_US.ISO8859-1/books/handbook/network-servers/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/network-servers/chapter.xml4911
-rw-r--r--en_US.ISO8859-1/books/handbook/pgpkeys/Makefile19
-rw-r--r--en_US.ISO8859-1/books/handbook/pgpkeys/chapter.xml39
-rw-r--r--en_US.ISO8859-1/books/handbook/ports/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/ports/chapter.xml1863
-rw-r--r--en_US.ISO8859-1/books/handbook/ppp-and-slip/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/ppp-and-slip/chapter.xml1679
-rw-r--r--en_US.ISO8859-1/books/handbook/preface/preface.xml760
-rw-r--r--en_US.ISO8859-1/books/handbook/printing/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/printing/chapter.xml1142
-rw-r--r--en_US.ISO8859-1/books/handbook/security/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/security/chapter.xml4157
-rw-r--r--en_US.ISO8859-1/books/handbook/serialcomms/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/serialcomms/chapter.xml2191
-rw-r--r--en_US.ISO8859-1/books/handbook/txtfiles.ent14
-rw-r--r--en_US.ISO8859-1/books/handbook/usb-device-mode/chapter.xml375
-rw-r--r--en_US.ISO8859-1/books/handbook/virtualization/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/virtualization/chapter.xml1844
-rw-r--r--en_US.ISO8859-1/books/handbook/wine/Makefile14
-rw-r--r--en_US.ISO8859-1/books/handbook/wine/chapter.xml1838
-rw-r--r--en_US.ISO8859-1/books/handbook/x11/Makefile15
-rw-r--r--en_US.ISO8859-1/books/handbook/x11/chapter.xml2228
-rw-r--r--en_US.ISO8859-1/books/handbook/zfs/chapter.xml4424
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/Makefile78
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/book.xml85
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/chapters.ent30
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/flavors/chapter.xml451
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/keeping-up/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/keeping-up/chapter.xml158
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/makefiles/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/makefiles/chapter.xml8260
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/new-port/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/new-port/chapter.xml48
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/order/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/order/chapter.xml551
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/pkg-files/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/pkg-files/chapter.xml448
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/plist/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/plist/chapter.xml1052
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-dads/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-dads/chapter.xml806
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-samplem/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-samplem/chapter.xml112
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-why/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/porting-why/chapter.xml22
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/quick-porting/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/quick-porting/chapter.xml441
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/security/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/security/chapter.xml468
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/slow-porting/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/slow-porting/chapter.xml570
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/special/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/special/chapter.xml7500
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/testing/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/testing/chapter.xml949
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/upgrading/Makefile15
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/upgrading/chapter.xml380
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/uses/chapter.xml3882
-rw-r--r--en_US.ISO8859-1/books/porters-handbook/versions/chapter.xml10693
186 files changed, 0 insertions, 173932 deletions
diff --git a/en_US.ISO8859-1/books/Makefile b/en_US.ISO8859-1/books/Makefile
deleted file mode 100644
index 9874dfb34e..0000000000
--- a/en_US.ISO8859-1/books/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $FreeBSD$
-
-SUBDIR = arch-handbook
-SUBDIR+= design-44bsd
-SUBDIR+= dev-model
-SUBDIR+= developers-handbook
-SUBDIR+= faq
-SUBDIR+= fdp-primer
-SUBDIR+= handbook
-SUBDIR+= porters-handbook
-
-ROOT_SYMLINKS= faq handbook
-
-DOC_PREFIX?= ${.CURDIR}/../..
-.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/en_US.ISO8859-1/books/Makefile.inc b/en_US.ISO8859-1/books/Makefile.inc
deleted file mode 100644
index 2bcfd06112..0000000000
--- a/en_US.ISO8859-1/books/Makefile.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# $FreeBSD$
-#
-
-DESTDIR?= ${DOCDIR}/en_US.ISO8859-1/books/${.CURDIR:T}
diff --git a/en_US.ISO8859-1/books/arch-handbook/Makefile b/en_US.ISO8859-1/books/arch-handbook/Makefile
deleted file mode 100644
index 5f933755f9..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/Makefile
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# $FreeBSD$
-#
-# Build the FreeBSD Architecture Handbook.
-#
-
-MAINTAINER=doc@FreeBSD.org
-
-DOC?= book
-
-FORMATS?= html-split
-
-INSTALL_COMPRESSED?= gz
-INSTALL_ONLY_COMPRESSED?=
-
-#
-# SRCS lists the individual XML files that make up the document. Changes
-# to any of these files will force a rebuild
-#
-
-# XML content
-SRCS= book.xml
-SRCS+= boot/chapter.xml
-SRCS+= driverbasics/chapter.xml
-SRCS+= isa/chapter.xml
-SRCS+= jail/chapter.xml
-SRCS+= kobj/chapter.xml
-SRCS+= locking/chapter.xml
-SRCS+= mac/chapter.xml
-SRCS+= newbus/chapter.xml
-SRCS+= pci/chapter.xml
-SRCS+= scsi/chapter.xml
-SRCS+= smp/chapter.xml
-SRCS+= sound/chapter.xml
-SRCS+= pccard/chapter.xml
-SRCS+= sysinit/chapter.xml
-SRCS+= usb/chapter.xml
-SRCS+= vm/chapter.xml
-
-# Images from the cross-document image library
-IMAGES_LIB= callouts/1.png
-IMAGES_LIB+= callouts/2.png
-IMAGES_LIB+= callouts/3.png
-IMAGES_LIB+= callouts/4.png
-IMAGES_LIB+= callouts/5.png
-IMAGES_LIB+= callouts/6.png
-IMAGES_LIB+= callouts/7.png
-IMAGES_LIB+= callouts/8.png
-IMAGES_LIB+= callouts/9.png
-IMAGES_LIB+= callouts/10.png
-
-# Entities
-
-URL_RELPREFIX?= ../../../..
-DOC_PREFIX?= ${.CURDIR}/../../..
-
-.include "${DOC_PREFIX}/share/mk/doc.project.mk"
diff --git a/en_US.ISO8859-1/books/arch-handbook/book.xml b/en_US.ISO8859-1/books/arch-handbook/book.xml
deleted file mode 100644
index 83fbc2a758..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/book.xml
+++ /dev/null
@@ -1,192 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE book PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
- "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd" [
-<!ENTITY % chapters SYSTEM "chapters.ent">
-%chapters;
-<!ENTITY % mac-entities SYSTEM "mac.ent">
-%mac-entities;
-]>
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD$
--->
-<book xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:lang="en">
-
- <info>
- <title>&os; Architecture Handbook</title>
-
- <author><orgname>The FreeBSD Documentation
- Project</orgname></author>
-
- <pubdate>$FreeBSD$</pubdate>
-
- <copyright>
- <year>2000</year>
- <year>2001</year>
- <year>2002</year>
- <year>2003</year>
- <year>2004</year>
- <year>2005</year>
- <year>2006</year>
- <year>2012</year>
- <year>2013</year>
- <holder>The FreeBSD Documentation Project</holder>
- </copyright>
-
- <legalnotice xml:id="trademarks" role="trademarks">
- &tm-attrib.freebsd;
- &tm-attrib.unix;
- &tm-attrib.apple;
- &tm-attrib.microsoft;
- &tm-attrib.general;
- </legalnotice>
-
- &legalnotice;
-
- <releaseinfo>$FreeBSD$</releaseinfo>
-
- <abstract>
- <para>Welcome to the &os; Architecture Handbook. This manual is
- a
- <emphasis>work in progress</emphasis> and is the work of many
- individuals. Many sections do not yet exist and some of those
- that do exist need to be updated. If you are interested in
- helping with this project, send email to the &a.doc;.</para>
-
- <para>The latest version of this document is always available
- from the <link xlink:href="&url.base;/index.html">FreeBSD
- World Wide Web server</link>. It may also be downloaded in
- a variety of formats and compression options from the <link
- xlink:href="https://download.freebsd.org/ftp/doc/">FreeBSD
- FTP server</link> or one of the numerous <link
- xlink:href="&url.books.handbook;/mirrors-ftp.html">mirror
- sites</link>.</para>
- </abstract>
- </info>
-
- <part xml:id="kernel">
- <title>Kernel</title>
-
- &chap.boot;
- &chap.locking;
- &chap.kobj;
- &chap.jail;
- &chap.sysinit;
- &chap.mac;
- &chap.vm;
- &chap.smp;
-
- </part>
-
- <part xml:id="devicedrivers">
- <title>Device Drivers</title>
-
- &chap.driverbasics;
- &chap.isa;
- &chap.pci;
- &chap.scsi;
- &chap.usb;
- &chap.newbus;
-
- &chap.snd;
- &chap.pccard;
-
- </part>
-
-<!-- XXX - finish me
- <part id="architectures">
- <title>Architectures</title>
-
- <chapter id="i386">
- <title>* I386</title>
-
- <para>Talk about <literal>i386</literal> specific &os;
- architecture.</para>
- </chapter>
-
- <chapter id="sparc64">
- <title>* SPARC64</title>
-
- <para>Talk about <literal>SPARC64</literal> specific &os;
- architecture.</para>
- </chapter>
-
- <chapter id="amd64">
- <title>* AMD64</title>
-
- <para>Talk about <literal>AMD64</literal> specific &os;
- architecture.</para>
- </chapter>
-
- <chapter id="powerpc">
- <title>* PowerPC</title>
-
- <para>Talk about <literal>PowerPC</literal> specific &os;
- architecture.</para>
- </chapter>
- </part>
--->
-
- <part xml:id="appendices">
- <title>Appendices</title>
-
- <bibliography>
-
- <biblioentry xreflabel="1">
- <authorgroup>
- <author>
- <personname>
- <firstname>Marshall</firstname>
- <othername role="Middle">Kirk</othername>
- <surname>McKusick</surname>
- </personname>
- </author>
- <author>
- <personname>
- <firstname>Keith</firstname>
- <surname>Bostic</surname>
- </personname>
- </author>
- <author>
- <personname>
- <firstname>Michael</firstname>
- <othername role="MI">J</othername>
- <surname>Karels</surname>
- </personname>
- </author>
- <author>
- <personname>
- <firstname>John</firstname>
- <othername role="MI">S</othername>
- <surname>Quarterman</surname>
- </personname>
- </author>
- </authorgroup>
-
- <copyright>
- <year>1996</year>
- <holder>Addison-Wesley Publishing Company, Inc.</holder>
- </copyright>
-
- <biblioid class="isbn">0-201-54979-4</biblioid>
-
- <publisher>
- <publishername>Addison-Wesley Publishing Company,
- Inc.</publishername>
- </publisher>
-
- <citetitle>The Design and Implementation of the 4.4 BSD
- Operating System</citetitle>
-
- <pagenums>1-2</pagenums>
- </biblioentry>
-
- </bibliography>
- </part>
-
- &chap.index;
-
-</book>
diff --git a/en_US.ISO8859-1/books/arch-handbook/boot/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/boot/chapter.xml
deleted file mode 100644
index 2ba2795fb3..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/boot/chapter.xml
+++ /dev/null
@@ -1,2396 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
-The FreeBSD Documentation Project
-
-Copyright (c) 2002 Sergey Lyubka <devnull@uptsoft.com>
-All rights reserved
-Copyright (c) 2014 Sergio Andr?s G?mez del Real <Sergio.G.delReal@gmail.com>
-All rights reserved
-$FreeBSD$
--->
-
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:id="boot">
-
- <info>
- <title>Bootstrapping and Kernel Initialization</title>
-
- <authorgroup>
- <author>
- <personname>
- <firstname>Sergey</firstname>
- <surname>Lyubka</surname>
- </personname>
-
- <contrib>Contributed by </contrib>
- </author>
- <!-- devnull@uptsoft.com 12 Jun 2002 -->
- </authorgroup>
-
- <authorgroup>
- <author>
- <personname>
- <firstname>Sergio Andr&eacute;s</firstname>
- <surname> G&oacute;mez del Real</surname>
- </personname>
-
- <contrib>Updated and enhanced by </contrib>
- </author>
- <!-- Sergio.G.DelReal@gmail.com Jan 2014 -->
- </authorgroup>
- </info>
-
- <sect1 xml:id="boot-synopsis">
- <title>Synopsis</title>
-
- <indexterm><primary>BIOS</primary></indexterm>
- <indexterm><primary>firmware</primary></indexterm>
- <indexterm><primary>POST</primary></indexterm>
- <indexterm><primary>IA-32</primary></indexterm>
- <indexterm><primary>booting</primary></indexterm>
- <indexterm><primary>system initialization</primary></indexterm>
- <para>This chapter is an overview of the boot and system
- initialization processes, starting from the
- <acronym>BIOS</acronym> (firmware) <acronym>POST</acronym>, to
- the first user process creation. Since the initial
- steps of system startup are very architecture dependent, the
- IA-32 architecture is used as an example.</para>
-
- <para>The &os; boot process can be surprisingly complex. After
- control is passed from the <acronym>BIOS</acronym>, a
- considerable amount of low-level configuration must be done
- before the kernel can be loaded and executed. This setup must
- be done in a simple and flexible manner, allowing the user a
- great deal of customization possibilities.</para>
- </sect1>
-
- <sect1 xml:id="boot-overview">
- <title>Overview</title>
-
- <para>The boot process is an extremely machine-dependent
- activity. Not only must code be written for every computer
- architecture, but there may also be multiple types of booting on
- the same architecture. For example, a directory listing of
- <filename>/usr/src/sys/boot</filename>
- reveals a great amount of architecture-dependent code. There is
- a directory for each of the various supported architectures. In
- the x86-specific <filename>i386</filename>
- directory, there are subdirectories for different boot standards
- like <filename>mbr</filename> (Master Boot Record),
- <filename>gpt</filename> (<acronym>GUID</acronym> Partition
- Table), and <filename>efi</filename> (Extensible Firmware
- Interface). Each boot standard has its own conventions and data
- structures. The example that follows shows booting an x86
- computer from an <acronym>MBR</acronym> hard drive with the &os;
- <filename>boot0</filename> multi-boot loader stored in the very
- first sector. That boot code starts the &os; three-stage boot
- process.</para>
-
- <para>The key to understanding this process is that it is a series
- of stages of increasing complexity. These stages are
- <filename>boot1</filename>, <filename>boot2</filename>, and
- <filename>loader</filename> (see &man.boot.8; for more detail).
- The boot system executes each stage in sequence. The last
- stage, <filename>loader</filename>, is responsible for loading
- the &os; kernel. Each stage is examined in the following
- sections.</para>
-
- <para>Here is an example of the output generated by the
- different boot stages. Actual output
- may differ from machine to machine:</para>
-
- <informaltable frame="none" pgwide="0">
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>&os; Component</entry>
- <entry>Output (may vary)</entry>
- </row>
-
- <row>
- <entry><literal>boot0</literal></entry>
- <entry><screen>F1 FreeBSD
-F2 BSD
-F5 Disk 2</screen></entry>
- </row>
-
- <row>
- <entry><literal>boot2</literal>
- <footnote><para>This prompt will appear if the user
- presses a key just after selecting an OS to boot at
- the <literal>boot0</literal>
- stage.</para></footnote></entry>
- <entry><screen>&gt;&gt;FreeBSD/i386 BOOT
-Default: 1:ad(1,a)/boot/loader
-boot:</screen></entry>
- </row>
-
- <row>
- <entry><filename>loader</filename></entry>
- <entry><screen>BTX loader 1.00 BTX version is 1.02
-Consoles: internal video/keyboard
-BIOS drive C: is disk0
-BIOS 639kB/2096064kB available memory
-
-FreeBSD/x86 bootstrap loader, Revision 1.1
-Console internal video/keyboard
-(root@snap.freebsd.org, Thu Jan 16 22:18:05 UTC 2014)
-Loading /boot/defaults/loader.conf
-/boot/kernel/kernel text=0xed9008 data=0x117d28+0x176650 syms=[0x8+0x137988+0x8+0x1515f8]</screen></entry>
- </row>
-
- <row>
- <entry>kernel</entry>
- <entry><screen>Copyright (c) 1992-2013 The FreeBSD Project.
-Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
- The Regents of the University of California. All rights reserved.
-FreeBSD is a registered trademark of The FreeBSD Foundation.
-FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014
- root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64
-FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610</screen></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect1>
-
- <sect1 xml:id="boot-bios">
- <title>The <acronym>BIOS</acronym></title>
-
- <para>When the computer powers on, the processor's registers are
- set to some predefined values. One of the registers is the
- <emphasis>instruction pointer</emphasis> register, and its value
- after a power on is well defined: it is a 32-bit value of
- <literal>0xfffffff0</literal>. The instruction pointer register
- (also known as the Program Counter) points to code to be
- executed by the processor. Another important register is the
- <literal>cr0</literal> 32-bit control register, and its value
- just after a reboot is <literal>0</literal>. One of
- <literal>cr0</literal>'s bits, the PE (Protection Enabled) bit,
- indicates whether the processor is running in 32-bit protected
- mode or 16-bit real mode. Since this bit is cleared at boot
- time, the processor boots in 16-bit real mode. Real mode means,
- among other things, that linear and physical addresses are
- identical. The reason for the processor not to start
- immediately in 32-bit protected mode is backwards compatibility.
- In particular, the boot process relies on the services provided
- by the <acronym>BIOS</acronym>, and the <acronym>BIOS</acronym>
- itself works in legacy, 16-bit code.</para>
-
- <para>The value of <literal>0xfffffff0</literal> is slightly less
- than 4&nbsp;GB, so unless the machine has 4&nbsp;GB of physical
- memory, it cannot point to a valid memory address. The
- computer's hardware translates this address so that it points to
- a <acronym>BIOS</acronym> memory block.</para>
-
- <para>The <acronym>BIOS</acronym> (Basic Input Output
- System) is a chip on the motherboard that has a relatively small
- amount of read-only memory (<acronym>ROM</acronym>). This
- memory contains various low-level routines that are specific to
- the hardware supplied with the motherboard. The processor will
- first jump to the address 0xfffffff0, which really resides in
- the <acronym>BIOS</acronym>'s memory. Usually this address
- contains a jump instruction to the <acronym>BIOS</acronym>'s
- POST routines.</para>
-
- <para>The <acronym>POST</acronym> (Power On Self Test)
- is a set of routines including the memory check, system bus
- check, and other low-level initialization so the
- <acronym>CPU</acronym> can set up the computer properly. The
- important step of this stage is determining the boot device.
- Modern <acronym>BIOS</acronym> implementations permit the
- selection of a boot device, allowing booting from a floppy,
- <acronym>CD-ROM</acronym>, hard disk, or other devices.</para>
-
- <para>The very last thing in the <acronym>POST</acronym> is the
- <literal>INT 0x19</literal> instruction. The
- <literal>INT 0x19</literal> handler reads 512 bytes from the
- first sector of boot device into the memory at address
- <literal>0x7c00</literal>. The term
- <emphasis>first sector</emphasis> originates from hard drive
- architecture, where the magnetic plate is divided into a number
- of cylindrical tracks. Tracks are numbered, and every track is
- divided into a number (usually 64) of sectors. Track numbers
- start at 0, but sector numbers start from 1. Track 0 is the
- outermost on the magnetic plate, and sector 1, the first sector,
- has a special purpose. It is also called the
- <acronym>MBR</acronym>, or Master Boot Record. The remaining
- sectors on the first track are never used.</para>
-
- <para>This sector is our boot-sequence starting point. As we will
- see, this sector contains a copy of our
- <filename>boot0</filename> program. A jump is made by the
- <acronym>BIOS</acronym> to address <literal>0x7c00</literal> so
- it starts executing.</para>
- </sect1>
-
- <sect1 xml:id="boot-boot0">
- <title>The Master Boot Record (<literal>boot0</literal>)</title>
-
- <indexterm><primary>MBR</primary></indexterm>
-
- <para>After control is received from the <acronym>BIOS</acronym>
- at memory address <literal>0x7c00</literal>,
- <filename>boot0</filename> starts executing. It is the first
- piece of code under &os; control. The task of
- <filename>boot0</filename> is quite simple: scan the partition
- table and let the user choose which partition to boot from. The
- Partition Table is a special, standard data structure embedded
- in the <acronym>MBR</acronym> (hence embedded in
- <filename>boot0</filename>) describing the four standard PC
- <quote>partitions</quote>
- <footnote>
- <para><link
- xlink:href="http://en.wikipedia.org/wiki/Master_boot_record"></link></para></footnote>.
- <filename>boot0</filename> resides in the filesystem as
- <filename>/boot/boot0</filename>. It is a small 512-byte file,
- and it is exactly what &os;'s installation procedure wrote to
- the hard disk's <acronym>MBR</acronym> if you chose the
- <quote>bootmanager</quote> option at installation time. Indeed,
- <filename>boot0</filename> <emphasis>is</emphasis> the
- <acronym>MBR</acronym>.</para>
-
- <para>As mentioned previously, the <literal>INT 0x19</literal>
- instruction causes the <literal>INT 0x19</literal> handler to
- load an <acronym>MBR</acronym> (<filename>boot0</filename>) into
- memory at address <literal>0x7c00</literal>. The source file
- for <filename>boot0</filename> can be found in
- <filename>sys/boot/i386/boot0/boot0.S</filename> - which is an
- awesome piece of code written by Robert Nordier.</para>
-
- <para>A special structure starting from offset
- <literal>0x1be</literal> in the <acronym>MBR</acronym> is called
- the <emphasis>partition table</emphasis>. It has four records
- of 16 bytes each, called <emphasis>partition records</emphasis>,
- which represent how the hard disk is partitioned, or, in &os;'s
- terminology, sliced. One byte of those 16 says whether a
- partition (slice) is bootable or not. Exactly one record must
- have that flag set, otherwise <filename>boot0</filename>'s code
- will refuse to proceed.</para>
-
- <para>A partition record has the following fields:</para>
-
- <itemizedlist>
- <listitem>
- <para>the 1-byte filesystem type</para>
- </listitem>
-
- <listitem>
- <para>the 1-byte bootable flag</para>
- </listitem>
-
- <listitem>
- <para>the 6 byte descriptor in CHS format</para>
- </listitem>
-
- <listitem>
- <para>the 8 byte descriptor in LBA format</para>
- </listitem>
- </itemizedlist>
-
- <para>A partition record descriptor contains information about
- where exactly the partition resides on the drive. Both
- descriptors, <acronym>LBA</acronym> and <acronym>CHS</acronym>,
- describe the same information, but in different ways:
- <acronym>LBA</acronym> (Logical Block Addressing) has the
- starting sector for the partition and the partition's length,
- while <acronym>CHS</acronym> (Cylinder Head Sector) has
- coordinates for the first and last sectors of the partition.
- The partition table ends with the special signature
- <literal>0xaa55</literal>.</para>
-
- <para>The <acronym>MBR</acronym> must fit into 512 bytes, a single
- disk sector. This program uses low-level <quote>tricks</quote>
- like taking advantage of the side effects of certain
- instructions and reusing register values from previous
- operations to make the most out of the fewest possible
- instructions. Care must also be taken when handling the
- partition table, which is embedded in the <acronym>MBR</acronym>
- itself. For these reasons, be very careful when modifying
- <filename>boot0.S</filename>.</para>
-
- <para>Note that the <filename>boot0.S</filename> source file
- is assembled <quote>as is</quote>: instructions are translated
- one by one to binary, with no additional information (no
- <acronym>ELF</acronym> file format, for example). This kind of
- low-level control is achieved at link time through special
- control flags passed to the linker. For example, the text
- section of the program is set to be located at address
- <literal>0x600</literal>. In practice this means that
- <filename>boot0</filename> must be loaded to memory address
- <literal>0x600</literal> in order to function properly.</para>
-
- <para>It is worth looking at the <filename>Makefile</filename> for
- <filename>boot0</filename>
- (<filename>sys/boot/i386/boot0/Makefile</filename>), as it
- defines some of the run-time behavior of
- <filename>boot0</filename>. For instance, if a terminal
- connected to the serial port (COM1) is used for I/O, the macro
- <literal>SIO</literal> must be defined
- (<literal>-DSIO</literal>). <literal>-DPXE</literal> enables
- boot through <acronym>PXE</acronym> by pressing
- <keycap>F6</keycap>. Additionally, the program defines a set of
- <emphasis>flags</emphasis> that allow further modification of
- its behavior. All of this is illustrated in the
- <filename>Makefile</filename>. For example, look at the
- linker directives which command the linker to start the text
- section at address <literal>0x600</literal>, and to build the
- output file <quote>as is</quote> (strip out any file
- formatting):</para>
-
- <figure xml:id="boot-boot0-makefile-as-is">
- <title><filename>sys/boot/i386/boot0/Makefile</filename></title>
-
- <programlisting> BOOT_BOOT0_ORG?=0x600
- LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} \
- -Wl,-N,-S,--oformat,binary</programlisting>
- </figure>
-
- <para>Let us now start our study of the <acronym>MBR</acronym>, or
- <filename>boot0</filename>, starting where execution
- begins.</para>
-
- <note>
- <para>Some modifications have been made to some instructions in
- favor of better exposition. For example, some macros are
- expanded, and some macro tests are omitted when the result of
- the test is known. This applies to all of the code examples
- shown.</para>
- </note>
-
- <figure xml:id="boot-boot0-entrypoint">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting>start:
- cld # String ops inc
- xorw %ax,%ax # Zero
- movw %ax,%es # Address
- movw %ax,%ds # data
- movw %ax,%ss # Set up
- movw 0x7c00,%sp # stack</programlisting>
- </figure>
-
- <para>This first block of code is the entry point of the program.
- It is where the <acronym>BIOS</acronym> transfers control.
- First, it makes sure that the string operations autoincrement
- its pointer operands (the <literal>cld</literal> instruction)
- <footnote>
- <para>When in doubt, we refer the reader to the official Intel
- manuals, which describe the exact semantics for each
- instruction: <link
- xlink:href="http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html"></link>.</para></footnote>.
- Then, as it makes no assumption about the state of the segment
- registers, it initializes them. Finally, it sets the stack
- pointer register (<literal>%sp</literal>) to address
- <literal>0x7c00</literal>, so we have a working stack.</para>
-
- <para>The next block is responsible for the relocation and
- subsequent jump to the relocated code.</para>
-
- <figure xml:id="boot-boot0-relocation">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting> movw $0x7c00,%si # Source
- movw $0x600,%di # Destination
- movw $512,%cx # Word count
- rep # Relocate
- movsb # code
- movw %di,%bp # Address variables
- movb $16,%cl # Words to clear
- rep # Zero
- stosb # them
- incb -0xe(%di) # Set the S field to 1
- jmp main-0x7c00+0x600 # Jump to relocated code</programlisting>
- </figure>
-
- <para>As <filename>boot0</filename> is loaded by the
- <acronym>BIOS</acronym> to address <literal>0x7C00</literal>, it
- copies itself to address <literal>0x600</literal> and then
- transfers control there (recall that it was linked to execute at
- address <literal>0x600</literal>). The source address,
- <literal>0x7c00</literal>, is copied to register
- <literal>%si</literal>. The destination address,
- <literal>0x600</literal>, to register <literal>%di</literal>.
- The number of bytes to copy, <literal>512</literal> (the
- program's size), is copied to register <literal>%cx</literal>.
- Next, the <literal>rep</literal> instruction repeats the
- instruction that follows, that is, <literal>movsb</literal>, the
- number of times dictated by the <literal>%cx</literal> register.
- The <literal>movsb</literal> instruction copies the byte pointed
- to by <literal>%si</literal> to the address pointed to by
- <literal>%di</literal>. This is repeated another 511 times. On
- each repetition, both the source and destination registers,
- <literal>%si</literal> and <literal>%di</literal>, are
- incremented by one. Thus, upon completion of the 512-byte copy,
- <literal>%di</literal> has the value
- <literal>0x600</literal>+<literal>512</literal>=
- <literal>0x800</literal>, and <literal>%si</literal> has the
- value <literal>0x7c00</literal>+<literal>512</literal>=
- <literal>0x7e00</literal>; we have thus completed the code
- <emphasis>relocation</emphasis>.</para>
-
- <para>Next, the destination register
- <literal>%di</literal> is copied to <literal>%bp</literal>.
- <literal>%bp</literal> gets the value <literal>0x800</literal>.
- The value <literal>16</literal> is copied to
- <literal>%cl</literal> in preparation for a new string operation
- (like our previous <literal>movsb</literal>). Now,
- <literal>stosb</literal> is executed 16 times. This instruction
- copies a <literal>0</literal> value to the address pointed to by
- the destination register (<literal>%di</literal>, which is
- <literal>0x800</literal>), and increments it. This is repeated
- another 15 times, so <literal>%di</literal> ends up with value
- <literal>0x810</literal>. Effectively, this clears the address
- range <literal>0x800</literal>-<literal>0x80f</literal>. This
- range is used as a (fake) partition table for writing the
- <acronym>MBR</acronym> back to disk. Finally, the sector field
- for the <acronym>CHS</acronym> addressing of this fake partition
- is given the value 1 and a jump is made to the main function
- from the relocated code. Note that until this jump to the
- relocated code, any reference to an absolute address was
- avoided.</para>
-
- <para>The following code block tests whether the drive number
- provided by the <acronym>BIOS</acronym> should be used, or
- the one stored in <filename>boot0</filename>.</para>
-
- <figure xml:id="boot-boot0-drivenumber">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting>main:
- testb $SETDRV,-69(%bp) # Set drive number?
- jnz disable_update # Yes
- testb %dl,%dl # Drive number valid?
- js save_curdrive # Possibly (0x80 set)</programlisting>
- </figure>
-
- <para>This code tests the <literal>SETDRV</literal> bit
- (<literal>0x20</literal>) in the <emphasis>flags</emphasis>
- variable. Recall that register <literal>%bp</literal> points to
- address location <literal>0x800</literal>, so the test is done
- to the <emphasis>flags</emphasis> variable at address
- <literal>0x800</literal>-<literal>69</literal>=
- <literal>0x7bb</literal>. This is an example of the type of
- modifications that can be done to <filename>boot0</filename>.
- The <literal>SETDRV</literal> flag is not set by default, but it
- can be set in the <filename>Makefile</filename>. When set, the
- drive number stored in the <acronym>MBR</acronym> is used
- instead of the one provided by the <acronym>BIOS</acronym>. We
- assume the defaults, and that the <acronym>BIOS</acronym>
- provided a valid drive number, so we jump to
- <literal>save_curdrive</literal>.</para>
-
- <para>The next block saves the drive number provided by the
- <acronym>BIOS</acronym>, and calls <literal>putn</literal> to
- print a new line on the screen.</para>
-
- <figure xml:id="boot-boot0-savedrivenumber">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting>save_curdrive:
- movb %dl, (%bp) # Save drive number
- pushw %dx # Also in the stack
-#ifdef TEST /* test code, print internal bios drive */
- rolb $1, %dl
- movw $drive, %si
- call putkey
-#endif
- callw putn # Print a newline</programlisting>
- </figure>
-
- <para>Note that we assume <varname>TEST</varname> is not defined,
- so the conditional code in it is not assembled and will not
- appear in our executable <filename>boot0</filename>.</para>
-
- <para>Our next block implements the actual scanning of the
- partition table. It prints to the screen the partition type for
- each of the four entries in the partition table. It compares
- each type with a list of well-known operating system file
- systems. Examples of recognized partition types are
- <acronym>NTFS</acronym> (&windows;, ID 0x7),
- <literal>ext2fs</literal> (&linux;, ID 0x83), and, of course,
- <literal>ffs</literal>/<literal>ufs2</literal> (&os;, ID 0xa5).
- The implementation is fairly simple.</para>
-
- <figure xml:id="boot-boot0-partition-scan">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting> movw $(partbl+0x4),%bx # Partition table (+4)
- xorw %dx,%dx # Item number
-
-read_entry:
- movb %ch,-0x4(%bx) # Zero active flag (ch == 0)
- btw %dx,_FLAGS(%bp) # Entry enabled?
- jnc next_entry # No
- movb (%bx),%al # Load type
- test %al, %al # skip empty partition
- jz next_entry
- movw $bootable_ids,%di # Lookup tables
- movb $(TLEN+1),%cl # Number of entries
- repne # Locate
- scasb # type
- addw $(TLEN-1), %di # Adjust
- movb (%di),%cl # Partition
- addw %cx,%di # description
- callw putx # Display it
-
-next_entry:
- incw %dx # Next item
- addb $0x10,%bl # Next entry
- jnc read_entry # Till done</programlisting>
- </figure>
-
- <para>It is important to note that the active flag for each entry
- is cleared, so after the scanning, <emphasis>no</emphasis>
- partition entry is active in our memory copy of
- <filename>boot0</filename>. Later, the active flag will be set
- for the selected partition. This ensures that only one active
- partition exists if the user chooses to write the changes back
- to disk.</para>
-
- <para>The next block tests for other drives. At startup,
- the <acronym>BIOS</acronym> writes the number of drives present
- in the computer to address <literal>0x475</literal>. If there
- are any other drives present, <filename>boot0</filename> prints
- the current drive to screen. The user may command
- <filename>boot0</filename> to scan partitions on another drive
- later.</para>
-
- <figure xml:id="boot-boot0-test-drives">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting> popw %ax # Drive number
- subb $0x79,%al # Does next
- cmpb 0x475,%al # drive exist? (from BIOS?)
- jb print_drive # Yes
- decw %ax # Already drive 0?
- jz print_prompt # Yes</programlisting>
- </figure>
-
- <para>We make the assumption that a single drive is present, so
- the jump to <literal>print_drive</literal> is not performed. We
- also assume nothing strange happened, so we jump to
- <literal>print_prompt</literal>.</para>
-
- <para>This next block just prints out a prompt followed by the
- default option:</para>
-
- <figure xml:id="boot-boot0-prompt">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting>print_prompt:
- movw $prompt,%si # Display
- callw putstr # prompt
- movb _OPT(%bp),%dl # Display
- decw %si # default
- callw putkey # key
- jmp start_input # Skip beep</programlisting>
- </figure>
-
- <para>Finally, a jump is performed to
- <literal>start_input</literal>, where the
- <acronym>BIOS</acronym> services are used to start a timer and
- for reading user input from the keyboard; if the timer expires,
- the default option will be selected:</para>
-
- <figure xml:id="boot-boot0-start-input">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting>start_input:
- xorb %ah,%ah # BIOS: Get
- int $0x1a # system time
- movw %dx,%di # Ticks when
- addw _TICKS(%bp),%di # timeout
-read_key:
- movb $0x1,%ah # BIOS: Check
- int $0x16 # for keypress
- jnz got_key # Have input
- xorb %ah,%ah # BIOS: int 0x1a, 00
- int $0x1a # get system time
- cmpw %di,%dx # Timeout?
- jb read_key # No</programlisting>
- </figure>
-
- <para>An interrupt is requested with number
- <literal>0x1a</literal> and argument <literal>0</literal> in
- register <literal>%ah</literal>. The <acronym>BIOS</acronym>
- has a predefined set of services, requested by applications as
- software-generated interrupts through the <literal>int</literal>
- instruction and receiving arguments in registers (in this case,
- <literal>%ah</literal>). Here, particularly, we are requesting
- the number of clock ticks since last midnight; this value is
- computed by the <acronym>BIOS</acronym> through the
- <acronym>RTC</acronym> (Real Time Clock). This clock can be
- programmed to work at frequencies ranging from 2&nbsp;Hz to
- 8192&nbsp;Hz. The <acronym>BIOS</acronym> sets it to
- 18.2&nbsp;Hz at startup. When the request is satisfied, a
- 32-bit result is returned by the <acronym>BIOS</acronym> in
- registers <literal>%cx</literal> and <literal>%dx</literal>
- (lower bytes in <literal>%dx</literal>). This result (the
- <literal>%dx</literal> part) is copied to register
- <literal>%di</literal>, and the value of the
- <varname>TICKS</varname> variable is added to
- <literal>%di</literal>. This variable resides in
- <filename>boot0</filename> at offset <literal>_TICKS</literal>
- (a negative value) from register <literal>%bp</literal> (which,
- recall, points to <literal>0x800</literal>). The default value
- of this variable is <literal>0xb6</literal> (182 in decimal).
- Now, the idea is that <filename>boot0</filename> constantly
- requests the time from the <acronym>BIOS</acronym>, and when the
- value returned in register <literal>%dx</literal> is greater
- than the value stored in <literal>%di</literal>, the time is up
- and the default selection will be made. Since the RTC ticks
- 18.2 times per second, this condition will be met after 10
- seconds (this default behavior can be changed in the
- <filename>Makefile</filename>). Until this time has passed,
- <filename>boot0</filename> continually asks the
- <acronym>BIOS</acronym> for any user input; this is done through
- <literal>int 0x16</literal>, argument <literal>1</literal> in
- <literal>%ah</literal>.</para>
-
- <para>Whether a key was pressed or the time expired, subsequent
- code validates the selection. Based on the selection, the
- register <literal>%si</literal> is set to point to the
- appropriate partition entry in the partition table. This new
- selection overrides the previous default one. Indeed, it
- becomes the new default. Finally, the ACTIVE flag of the
- selected partition is set. If it was enabled at compile time,
- the in-memory version of <filename>boot0</filename> with these
- modified values is written back to the <acronym>MBR</acronym> on
- disk. We leave the details of this implementation to the
- reader.</para>
-
- <para>We now end our study with the last code block from the
- <filename>boot0</filename> program:</para>
-
- <figure xml:id="boot-boot0-check-bootable">
- <title><filename>sys/boot/i386/boot0/boot0.S</filename></title>
-
- <programlisting> movw $0x7c00,%bx # Address for read
- movb $0x2,%ah # Read sector
- callw intx13 # from disk
- jc beep # If error
- cmpw $0xaa55,0x1fe(%bx) # Bootable?
- jne beep # No
- pushw %si # Save ptr to selected part.
- callw putn # Leave some space
- popw %si # Restore, next stage uses it
- jmp *%bx # Invoke bootstrap</programlisting>
- </figure>
-
- <para>Recall that <literal>%si</literal> points to the selected
- partition entry. This entry tells us where the partition begins
- on disk. We assume, of course, that the partition selected is
- actually a &os; slice.</para>
-
- <note>
- <para>From now on, we will favor the use of the technically
- more accurate term <quote>slice</quote> rather than
- <quote>partition</quote>.</para>
- </note>
-
- <para>The transfer buffer is set to <literal>0x7c00</literal>
- (register <literal>%bx</literal>), and a read for the first
- sector of the &os; slice is requested by calling
- <literal>intx13</literal>. We assume that everything went okay,
- so a jump to <literal>beep</literal> is not performed. In
- particular, the new sector read must end with the magic sequence
- <literal>0xaa55</literal>. Finally, the value at
- <literal>%si</literal> (the pointer to the selected partition
- table) is preserved for use by the next stage, and a jump is
- performed to address <literal>0x7c00</literal>, where execution
- of our next stage (the just-read block) is started.</para>
- </sect1>
-
- <sect1 xml:id="boot-boot1">
- <title><literal>boot1</literal> Stage</title>
-
- <para>So far we have gone through the following sequence:</para>
-
- <itemizedlist>
- <listitem>
- <para>The <acronym>BIOS</acronym> did some early hardware
- initialization, including the <acronym>POST</acronym>. The
- <acronym>MBR</acronym> (<filename>boot0</filename>) was
- loaded from absolute disk sector one to address
- <literal>0x7c00</literal>. Execution control was passed to
- that location.</para>
- </listitem>
-
- <listitem>
- <para><filename>boot0</filename> relocated itself to the
- location it was linked to execute
- (<literal>0x600</literal>), followed by a jump to continue
- execution at the appropriate place. Finally,
- <filename>boot0</filename> loaded the first disk sector from
- the &os; slice to address <literal>0x7c00</literal>.
- Execution control was passed to that location.</para>
- </listitem>
- </itemizedlist>
-
- <para><filename>boot1</filename> is the next step in the
- boot-loading sequence. It is the first of three boot stages.
- Note that we have been dealing exclusively
- with disk sectors. Indeed, the <acronym>BIOS</acronym> loads
- the absolute first sector, while <filename>boot0</filename>
- loads the first sector of the &os; slice. Both loads are to
- address <literal>0x7c00</literal>. We can conceptually think of
- these disk sectors as containing the files
- <filename>boot0</filename> and <filename>boot1</filename>,
- respectively, but in reality this is not entirely true for
- <filename>boot1</filename>. Strictly speaking, unlike
- <filename>boot0</filename>, <filename>boot1</filename> is not
- part of the boot blocks
- <footnote>
- <para>There is a file <filename>/boot/boot1</filename>, but it
- is not the written to the beginning of the &os; slice.
- Instead, it is concatenated with <filename>boot2</filename>
- to form <filename>boot</filename>, which
- <emphasis>is</emphasis> written to the beginning of the &os;
- slice and read at boot time.</para></footnote>.
- Instead, a single, full-blown file, <filename>boot</filename>
- (<filename>/boot/boot</filename>), is what ultimately is
- written to disk. This file is a combination of
- <filename>boot1</filename>, <filename>boot2</filename> and the
- <literal>Boot Extender</literal> (or <acronym>BTX</acronym>).
- This single file is greater in size than a single sector
- (greater than 512 bytes). Fortunately,
- <filename>boot1</filename> occupies <emphasis>exactly</emphasis>
- the first 512 bytes of this single file, so when
- <filename>boot0</filename> loads the first sector of the &os;
- slice (512 bytes), it is actually loading
- <filename>boot1</filename> and transferring control to
- it.</para>
-
- <para>The main task of <filename>boot1</filename> is to load the
- next boot stage. This next stage is somewhat more complex. It
- is composed of a server called the <quote>Boot Extender</quote>,
- or <acronym>BTX</acronym>, and a client, called
- <filename>boot2</filename>. As we will see, the last boot
- stage, <filename>loader</filename>, is also a client of the
- <acronym>BTX</acronym> server.</para>
-
- <para>Let us now look in detail at what exactly is done by
- <filename>boot1</filename>, starting like we did for
- <filename>boot0</filename>, at its entry point:</para>
-
- <figure xml:id="boot-boot1-entry">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>start:
- jmp main</programlisting>
- </figure>
-
- <para>The entry point at <literal>start</literal> simply jumps
- past a special data area to the label <literal>main</literal>,
- which in turn looks like this:</para>
-
- <figure xml:id="boot-boot1-main">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>main:
- cld # String ops inc
- xor %cx,%cx # Zero
- mov %cx,%es # Address
- mov %cx,%ds # data
- mov %cx,%ss # Set up
- mov $start,%sp # stack
- mov %sp,%si # Source
- mov $0x700,%di # Destination
- incb %ch # Word count
- rep # Copy
- movsw # code</programlisting>
- </figure>
-
- <para>Just like <filename>boot0</filename>, this
- code relocates <filename>boot1</filename>,
- this time to memory address <literal>0x700</literal>. However,
- unlike <filename>boot0</filename>, it does not jump there.
- <filename>boot1</filename> is linked to execute at
- address <literal>0x7c00</literal>, effectively where it was
- loaded in the first place. The reason for this relocation will
- be discussed shortly.</para>
-
- <para>Next comes a loop that looks for the &os; slice. Although
- <filename>boot0</filename> loaded <filename>boot1</filename>
- from the &os; slice, no information was passed to it about this
- <footnote>
- <para>Actually we did pass a pointer to the slice entry in
- register <literal>%si</literal>. However,
- <filename>boot1</filename> does not assume that it was
- loaded by <filename>boot0</filename> (perhaps some other
- <acronym>MBR</acronym> loaded it, and did not pass this
- information), so it assumes nothing.</para></footnote>,
- so <filename>boot1</filename> must rescan the
- partition table to find where the &os; slice starts. Therefore
- it rereads the <acronym>MBR</acronym>:</para>
-
- <figure xml:id="boot-boot1-find-freebsd">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting> mov $part4,%si # Partition
- cmpb $0x80,%dl # Hard drive?
- jb main.4 # No
- movb $0x1,%dh # Block count
- callw nread # Read MBR</programlisting>
- </figure>
-
- <para>In the code above, register <literal>%dl</literal>
- maintains information about the boot device. This is passed on
- by the <acronym>BIOS</acronym> and preserved by the
- <acronym>MBR</acronym>. Numbers <literal>0x80</literal> and
- greater tells us that we are dealing with a hard drive, so a
- call is made to <literal>nread</literal>, where the
- <acronym>MBR</acronym> is read. Arguments to
- <literal>nread</literal> are passed through
- <literal>%si</literal> and <literal>%dh</literal>. The memory
- address at label <literal>part4</literal> is copied to
- <literal>%si</literal>. This memory address holds a
- <quote>fake partition</quote> to be used by
- <literal>nread</literal>. The following is the data in the fake
- partition:</para>
-
- <figure xml:id="boot-boot2-make-fake-partition">
- <title><filename>sys/boot/i386/boot2/Makefile</filename></title>
-
- <programlisting> part4:
- .byte 0x80, 0x00, 0x01, 0x00
- .byte 0xa5, 0xfe, 0xff, 0xff
- .byte 0x00, 0x00, 0x00, 0x00
- .byte 0x50, 0xc3, 0x00, 0x00</programlisting>
- </figure>
-
- <para>In particular, the <acronym>LBA</acronym> for this fake
- partition is hardcoded to zero. This is used as an argument to
- the <acronym>BIOS</acronym> for reading absolute sector one from
- the hard drive. Alternatively, CHS addressing could be used.
- In this case, the fake partition holds cylinder 0, head 0 and
- sector 1, which is equivalent to absolute sector one.</para>
-
- <para>Let us now proceed to take a look at
- <literal>nread</literal>:</para>
-
- <figure xml:id="boot-boot1-nread">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>nread:
- mov $0x8c00,%bx # Transfer buffer
- mov 0x8(%si),%ax # Get
- mov 0xa(%si),%cx # LBA
- push %cs # Read from
- callw xread.1 # disk
- jnc return # If success, return</programlisting>
- </figure>
-
- <para>Recall that <literal>%si</literal> points to the fake
- partition. The word
- <footnote>
- <para>In the context of 16-bit real mode, a word is 2
- bytes.</para></footnote>
- at offset <literal>0x8</literal> is copied to register
- <literal>%ax</literal> and word at offset <literal>0xa</literal>
- to <literal>%cx</literal>. They are interpreted by the
- <acronym>BIOS</acronym> as the lower 4-byte value denoting the
- LBA to be read (the upper four bytes are assumed to be zero).
- Register <literal>%bx</literal> holds the memory address where
- the <acronym>MBR</acronym> will be loaded. The instruction
- pushing <literal>%cs</literal> onto the stack is very
- interesting. In this context, it accomplishes nothing.
- However, as we will see shortly, <filename>boot2</filename>, in
- conjunction with the <acronym>BTX</acronym> server, also uses
- <literal>xread.1</literal>. This mechanism will be discussed in
- the next section.</para>
-
- <para>The code at <literal>xread.1</literal> further calls
- the <literal>read</literal> function, which actually calls the
- <acronym>BIOS</acronym> asking for the disk sector:</para>
-
- <figure xml:id="boot-boot1-xread1">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>xread.1:
- pushl $0x0 # absolute
- push %cx # block
- push %ax # number
- push %es # Address of
- push %bx # transfer buffer
- xor %ax,%ax # Number of
- movb %dh,%al # blocks to
- push %ax # transfer
- push $0x10 # Size of packet
- mov %sp,%bp # Packet pointer
- callw read # Read from disk
- lea 0x10(%bp),%sp # Clear stack
- lret # To far caller</programlisting>
- </figure>
-
- <para>Note the long return instruction at the end of this block.
- This instruction pops out the <literal>%cs</literal> register
- pushed by <literal>nread</literal>, and returns. Finally,
- <literal>nread</literal> also returns.</para>
-
- <para>With the <acronym>MBR</acronym> loaded to memory, the actual
- loop for searching the &os; slice begins:</para>
-
- <figure xml:id="boot-boot1-find-part">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting> mov $0x1,%cx # Two passes
-main.1:
- mov $0x8dbe,%si # Partition table
- movb $0x1,%dh # Partition
-main.2:
- cmpb $0xa5,0x4(%si) # Our partition type?
- jne main.3 # No
- jcxz main.5 # If second pass
- testb $0x80,(%si) # Active?
- jnz main.5 # Yes
-main.3:
- add $0x10,%si # Next entry
- incb %dh # Partition
- cmpb $0x5,%dh # In table?
- jb main.2 # Yes
- dec %cx # Do two
- jcxz main.1 # passes</programlisting>
- </figure>
-
- <para>If a &os; slice is identified, execution continues at
- <literal>main.5</literal>. Note that when a &os; slice is found
- <literal>%si</literal> points to the appropriate entry in the
- partition table, and <literal>%dh</literal> holds the partition
- number. We assume that a &os; slice is found, so we continue
- execution at <literal>main.5</literal>:</para>
-
- <figure xml:id="boot-boot1-main5">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>main.5:
- mov %dx,0x900 # Save args
- movb $0x10,%dh # Sector count
- callw nread # Read disk
- mov $0x9000,%bx # BTX
- mov 0xa(%bx),%si # Get BTX length and set
- add %bx,%si # %si to start of boot2.bin
- mov $0xc000,%di # Client page 2
- mov $0xa200,%cx # Byte
- sub %si,%cx # count
- rep # Relocate
- movsb # client</programlisting>
- </figure>
-
- <para>Recall that at this point, register <literal>%si</literal>
- points to the &os; slice entry in the <acronym>MBR</acronym>
- partition table, so a call to <literal>nread</literal> will
- effectively read sectors at the beginning of this partition.
- The argument passed on register <literal>%dh</literal> tells
- <literal>nread</literal> to read 16 disk sectors. Recall that
- the first 512 bytes, or the first sector of the &os; slice,
- coincides with the <filename>boot1</filename> program. Also
- recall that the file written to the beginning of the &os;
- slice is not <filename>/boot/boot1</filename>, but
- <filename>/boot/boot</filename>. Let us look at the size of
- these files in the filesystem:</para>
-
- <screen xml:id="boot-boot1-filesize">-r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot0
--r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot1
--r--r--r-- 1 root wheel 7.5K Jan 8 00:15 /boot/boot2
--r--r--r-- 1 root wheel 8.0K Jan 8 00:15 /boot/boot</screen>
-
- <para>Both <filename>boot0</filename> and
- <filename>boot1</filename> are 512 bytes each, so they fit
- <emphasis>exactly</emphasis> in one disk sector.
- <filename>boot2</filename> is much bigger, holding both
- the <acronym>BTX</acronym> server and the
- <filename>boot2</filename> client. Finally, a file called
- simply <filename>boot</filename> is 512 bytes larger than
- <filename>boot2</filename>. This file is a
- concatenation of <filename>boot1</filename> and
- <filename>boot2</filename>. As already noted,
- <filename>boot0</filename> is the file written to the absolute
- first disk sector (the <acronym>MBR</acronym>), and
- <filename>boot</filename> is the file written to the first
- sector of the &os; slice; <filename>boot1</filename> and
- <filename>boot2</filename> are <emphasis>not</emphasis> written
- to disk. The command used to concatenate
- <filename>boot1</filename> and <filename>boot2</filename> into a
- single <filename>boot</filename> is merely
- <command>cat boot1 boot2 &gt; boot</command>.</para>
-
- <para>So <filename>boot1</filename> occupies exactly the first 512
- bytes of <filename>boot</filename> and, because
- <filename>boot</filename> is written to the first sector of the
- &os; slice, <filename>boot1</filename> fits exactly in this
- first sector. When <literal>nread</literal> reads the first
- 16 sectors of the &os; slice, it effectively reads the entire
- <filename>boot</filename> file
- <footnote>
- <para>512*16=8192 bytes, exactly the size of
- <filename>boot</filename></para></footnote>.
- We will see more details about how <filename>boot</filename> is
- formed from <filename>boot1</filename> and
- <filename>boot2</filename> in the next section.</para>
-
- <para>Recall that <literal>nread</literal> uses memory address
- <literal>0x8c00</literal> as the transfer buffer to hold the
- sectors read. This address is conveniently chosen. Indeed,
- because <filename>boot1</filename> belongs to the first 512
- bytes, it ends up in the address range
- <literal>0x8c00</literal>-<literal>0x8dff</literal>. The 512
- bytes that follows (range
- <literal>0x8e00</literal>-<literal>0x8fff</literal>) is used to
- store the <emphasis>bsdlabel</emphasis>
- <footnote>
- <para>Historically known as <quote>disklabel</quote>. If you
- ever wondered where &os; stored this information, it is in
- this region. See &man.bsdlabel.8;</para></footnote>.</para>
-
- <para>Starting at address <literal>0x9000</literal> is the
- beginning of the <acronym>BTX</acronym> server, and immediately
- following is the <filename>boot2</filename> client. The
- <acronym>BTX</acronym> server acts as a kernel, and executes in
- protected mode in the most privileged level. In contrast, the
- <acronym>BTX</acronym> clients (<filename>boot2</filename>, for
- example), execute in user mode. We will see how this is
- accomplished in the next section. The code after the call to
- <literal>nread</literal> locates the beginning of
- <filename>boot2</filename> in the memory buffer, and copies it
- to memory address <literal>0xc000</literal>. This is because
- the <acronym>BTX</acronym> server arranges
- <filename>boot2</filename> to execute in a segment starting at
- <literal>0xa000</literal>. We explore this in detail in the
- following section.</para>
-
- <para>The last code block of <filename>boot1</filename> enables
- access to memory above 1MB
- <footnote>
- <para>This is necessary for legacy reasons. Interested
- readers should see <link
- xlink:href="http://en.wikipedia.org/wiki/A20_line"/>.</para></footnote>
- and concludes with a jump to the starting point of the
- <acronym>BTX</acronym> server:</para>
-
- <figure xml:id="boot-boot1-seta20">
- <title><filename>sys/boot/i386/boot2/boot1.S</filename></title>
-
- <programlisting>seta20:
- cli # Disable interrupts
-seta20.1:
- dec %cx # Timeout?
- jz seta20.3 # Yes
-
- inb $0x64,%al # Get status
- testb $0x2,%al # Busy?
- jnz seta20.1 # Yes
- movb $0xd1,%al # Command: Write
- outb %al,$0x64 # output port
-seta20.2:
- inb $0x64,%al # Get status
- testb $0x2,%al # Busy?
- jnz seta20.2 # Yes
- movb $0xdf,%al # Enable
- outb %al,$0x60 # A20
-seta20.3:
- sti # Enable interrupts
- jmp 0x9010 # Start BTX</programlisting>
- </figure>
-
- <para>Note that right before the jump, interrupts are
- enabled.</para>
- </sect1>
-
- <sect1 xml:id="btx-server">
- <title>The <acronym>BTX</acronym> Server</title>
-
- <para>Next in our boot sequence is the
- <acronym>BTX</acronym> Server. Let us quickly remember how we
- got here:</para>
-
- <itemizedlist>
- <listitem>
- <para>The <acronym>BIOS</acronym> loads the absolute sector
- one (the <acronym>MBR</acronym>, or
- <filename>boot0</filename>), to address
- <literal>0x7c00</literal> and jumps there.</para>
- </listitem>
-
- <listitem>
- <para><filename>boot0</filename> relocates itself to
- <literal>0x600</literal>, the address it was linked to
- execute, and jumps over there. It then reads the first
- sector of the &os; slice (which consists of
- <filename>boot1</filename>) into address
- <literal>0x7c00</literal> and jumps over there.</para>
- </listitem>
-
- <listitem>
- <para><filename>boot1</filename> loads the first 16 sectors
- of the &os; slice into address <literal>0x8c00</literal>.
- This 16 sectors, or 8192 bytes, is the whole file
- <filename>boot</filename>. The file is a
- concatenation of <filename>boot1</filename> and
- <filename>boot2</filename>. <filename>boot2</filename>, in
- turn, contains the <acronym>BTX</acronym> server and the
- <filename>boot2</filename> client. Finally, a jump is made
- to address <literal>0x9010</literal>, the entry point of the
- <acronym>BTX</acronym> server.</para>
- </listitem>
- </itemizedlist>
-
- <para>Before studying the <acronym>BTX</acronym> Server in detail,
- let us further review how the single, all-in-one
- <filename>boot</filename> file is created. The way
- <filename>boot</filename> is built is defined in its
- <filename>Makefile</filename>
- (<filename>/usr/src/sys/boot/i386/boot2/Makefile</filename>).
- Let us look at the rule that creates the
- <filename>boot</filename> file:</para>
-
- <figure xml:id="boot-boot1-make-boot">
- <title><filename>sys/boot/i386/boot2/Makefile</filename></title>
-
- <programlisting> boot: boot1 boot2
- cat boot1 boot2 > boot</programlisting>
- </figure>
-
- <para>This tells us that <filename>boot1</filename> and
- <filename>boot2</filename> are needed, and the rule simply
- concatenates them to produce a single file called
- <filename>boot</filename>. The rules for creating
- <filename>boot1</filename> are also quite simple:</para>
-
- <figure xml:id="boot-boot1-make-boot1">
- <title><filename>sys/boot/i386/boot2/Makefile</filename></title>
-
- <programlisting> boot1: boot1.out
- objcopy -S -O binary boot1.out boot1
-
- boot1.out: boot1.o
- ld -e start -Ttext 0x7c00 -o boot1.out boot1.o</programlisting>
- </figure>
-
- <para>To apply the rule for creating
- <filename>boot1</filename>, <filename>boot1.out</filename> must
- be resolved. This, in turn, depends on the existence of
- <filename>boot1.o</filename>. This last file is simply the
- result of assembling our familiar <filename>boot1.S</filename>,
- without linking. Now, the rule for creating
- <filename>boot1.out</filename> is applied. This tells us that
- <filename>boot1.o</filename> should be linked with
- <literal>start</literal> as its entry point, and starting at
- address <literal>0x7c00</literal>. Finally,
- <filename>boot1</filename> is created from
- <filename>boot1.out</filename> applying the appropriate rule.
- This rule is the <filename>objcopy</filename> command applied to
- <filename>boot1.out</filename>. Note the flags passed to
- <filename>objcopy</filename>: <literal>-S</literal> tells it to
- strip all relocation and symbolic information;
- <literal>-O binary</literal> indicates the output format, that
- is, a simple, unformatted binary file.</para>
-
- <para>Having <filename>boot1</filename>, let us take a look at how
- <filename>boot2</filename> is constructed:</para>
-
- <figure xml:id="boot-boot1-make-boot2">
- <title><filename>sys/boot/i386/boot2/Makefile</filename></title>
-
- <programlisting> boot2: boot2.ld
- @set -- `ls -l boot2.ld`; x=$$((7680-$$5)); \
- echo "$$x bytes available"; test $$x -ge 0
- dd if=boot2.ld of=boot2 obs=7680 conv=osync
-
- boot2.ld: boot2.ldr boot2.bin ../btx/btx/btx
- btxld -v -E 0x2000 -f bin -b ../btx/btx/btx -l boot2.ldr \
- -o boot2.ld -P 1 boot2.bin
-
- boot2.ldr:
- dd if=/dev/zero of=boot2.ldr bs=512 count=1
-
- boot2.bin: boot2.out
- objcopy -S -O binary boot2.out boot2.bin
-
- boot2.out: ../btx/lib/crt0.o boot2.o sio.o
- ld -Ttext 0x2000 -o boot2.out
-
- boot2.o: boot2.s
- ${CC} ${ACFLAGS} -c boot2.s
-
- boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c
- ${CC} ${CFLAGS} -S -o boot2.s.tmp ${.CURDIR}/boot2.c
- sed -e '/align/d' -e '/nop/d' "MISSING" boot2.s.tmp > boot2.s
- rm -f boot2.s.tmp
-
- boot2.h: boot1.out
- ${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \
- { x = $$1 - ORG1; \
- printf("#define XREADORG %#x\n", REL1 + x) }' \
- ORG1=`printf "%d" ${ORG1}` \
- REL1=`printf "%d" ${REL1}` > ${.TARGET}</programlisting>
- </figure>
-
- <para>The mechanism for building <filename>boot2</filename> is
- far more elaborate. Let us point out the most relevant facts.
- The dependency list is as follows:</para>
-
- <figure xml:id="boot-boot1-make-boot2-more">
- <title><filename>sys/boot/i386/boot2/Makefile</filename></title>
-
- <programlisting> boot2: boot2.ld
- boot2.ld: boot2.ldr boot2.bin ${BTXDIR}/btx/btx
- boot2.bin: boot2.out
- boot2.out: ${BTXDIR}/lib/crt0.o boot2.o sio.o
- boot2.o: boot2.s
- boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c
- boot2.h: boot1.out</programlisting>
- </figure>
-
- <para>Note that initially there is no header file
- <filename>boot2.h</filename>, but its creation depends on
- <filename>boot1.out</filename>, which we already have. The rule
- for its creation is a bit terse, but the important thing is that
- the output, <filename>boot2.h</filename>, is something like
- this:</para>
-
- <figure xml:id="boot-boot1-make-boot2h">
- <title><filename>sys/boot/i386/boot2/boot2.h</filename></title>
-
- <programlisting>#define XREADORG 0x725</programlisting>
- </figure>
-
- <para>Recall that <filename>boot1</filename> was relocated (i.e.,
- copied from <literal>0x7c00</literal> to
- <literal>0x700</literal>). This relocation will now make sense,
- because as we will see, the <acronym>BTX</acronym> server
- reclaims some memory, including the space where
- <filename>boot1</filename> was originally loaded. However, the
- <acronym>BTX</acronym> server needs access to
- <filename>boot1</filename>'s <literal>xread</literal> function;
- this function, according to the output of
- <filename>boot2.h</filename>, is at location
- <literal>0x725</literal>. Indeed, the
- <acronym>BTX</acronym> server uses the
- <literal>xread</literal> function from
- <filename>boot1</filename>'s relocated code. This function is
- now accessible from within the <filename>boot2</filename>
- client.</para>
-
- <para>We next build <filename>boot2.s</filename> from files
- <filename>boot2.h</filename>, <filename>boot2.c</filename> and
- <filename>/usr/src/sys/boot/common/ufsread.c</filename>. The
- rule for this is to compile the code in
- <filename>boot2.c</filename> (which includes
- <filename>boot2.h</filename> and <filename>ufsread.c</filename>)
- into assembly code. Having <filename>boot2.s</filename>, the
- next rule assembles <filename>boot2.s</filename>, creating the
- object file <filename>boot2.o</filename>. The
- next rule directs the linker to link various files
- (<filename>crt0.o</filename>,
- <filename>boot2.o</filename> and <filename>sio.o</filename>).
- Note that the output file, <filename>boot2.out</filename>, is
- linked to execute at address <literal>0x2000</literal>. Recall
- that <filename>boot2</filename> will be executed in user mode,
- within a special user segment set up by the
- <acronym>BTX</acronym> server. This segment starts at
- <literal>0xa000</literal>. Also, remember that the
- <filename>boot2</filename> portion of <filename>boot</filename>
- was copied to address <literal>0xc000</literal>, that is, offset
- <literal>0x2000</literal> from the start of the user segment, so
- <filename>boot2</filename> will work properly when we transfer
- control to it. Next, <filename>boot2.bin</filename> is created
- from <filename>boot2.out</filename> by stripping its symbols and
- format information; boot2.bin is a <emphasis>raw</emphasis>
- binary. Now, note that a file <filename>boot2.ldr</filename> is
- created as a 512-byte file full of zeros. This space is
- reserved for the bsdlabel.</para>
-
- <para>Now that we have files <filename>boot1</filename>,
- <filename>boot2.bin</filename> and
- <filename>boot2.ldr</filename>, only the
- <acronym>BTX</acronym> server is missing before creating the
- all-in-one <filename>boot</filename> file. The
- <acronym>BTX</acronym> server is located in
- <filename>/usr/src/sys/boot/i386/btx/btx</filename>; it has its
- own <filename>Makefile</filename> with its own set of rules for
- building. The important thing to notice is that it is also
- compiled as a <emphasis>raw</emphasis> binary, and that it is
- linked to execute at address <literal>0x9000</literal>. The
- details can be found in
- <filename>/usr/src/sys/boot/i386/btx/btx/Makefile</filename>.</para>
-
- <para>Having the files that comprise the <filename>boot</filename>
- program, the final step is to <emphasis>merge</emphasis> them.
- This is done by a special program called
- <filename>btxld</filename> (source located in
- <filename>/usr/src/usr.sbin/btxld</filename>). Some arguments
- to this program include the name of the output file
- (<filename>boot</filename>), its entry point
- (<literal>0x2000</literal>) and its file format
- (raw binary). The various files are
- finally merged by this utility into the file
- <filename>boot</filename>, which consists of
- <filename>boot1</filename>, <filename>boot2</filename>, the
- <literal>bsdlabel</literal> and the
- <acronym>BTX</acronym> server. This file, which takes
- exactly 16 sectors, or 8192 bytes, is what is
- actually written to the beginning of the &os; slice
- during installation. Let us now proceed to study the
- <acronym>BTX</acronym> server program.</para>
-
- <para>The <acronym>BTX</acronym> server prepares a simple
- environment and switches from 16-bit real mode to 32-bit
- protected mode, right before passing control to the client.
- This includes initializing and updating the following data
- structures:</para>
-
- <indexterm><primary>virtual v86 mode</primary></indexterm>
- <itemizedlist>
- <listitem>
- <para>Modifies the
- <literal>Interrupt Vector Table (IVT)</literal>. The
- <acronym>IVT</acronym> provides exception and interrupt
- handlers for Real-Mode code.</para>
- </listitem>
-
- <listitem>
- <para>The <literal>Interrupt Descriptor Table (IDT)</literal>
- is created. Entries are provided for processor exceptions,
- hardware interrupts, two system calls and V86 interface.
- The IDT provides exception and interrupt handlers for
- Protected-Mode code.</para>
- </listitem>
-
- <listitem>
- <para>A <literal>Task-State Segment (TSS)</literal> is
- created. This is necessary because the processor works in
- the <emphasis>least</emphasis> privileged level when
- executing the client (<filename>boot2</filename>), but in
- the <emphasis>most</emphasis> privileged level when
- executing the <acronym>BTX</acronym> server.</para>
- </listitem>
-
- <listitem>
- <para>The <acronym>GDT</acronym> (Global Descriptor Table) is
- set up. Entries (descriptors) are provided for
- supervisor code and data, user code and data, and real-mode
- code and data.
- <footnote>
- <para>Real-mode code and data are necessary when switching
- back to real mode from protected mode, as suggested by
- the Intel manuals.</para></footnote></para>
- </listitem>
- </itemizedlist>
-
- <para>Let us now start studying the actual implementation. Recall
- that <filename>boot1</filename> made a jump to address
- <literal>0x9010</literal>, the <acronym>BTX</acronym> server's
- entry point. Before studying program execution there,
- note that the <acronym>BTX</acronym> server has a special header
- at address range <literal>0x9000-0x900f</literal>, right before
- its entry point. This header is defined as follows:</para>
-
- <figure xml:id="btx-header">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>start: # Start of code
-/*
- * BTX header.
- */
-btx_hdr: .byte 0xeb # Machine ID
- .byte 0xe # Header size
- .ascii "BTX" # Magic
- .byte 0x1 # Major version
- .byte 0x2 # Minor version
- .byte BTX_FLAGS # Flags
- .word PAG_CNT-MEM_ORG>>0xc # Paging control
- .word break-start # Text size
- .long 0x0 # Entry address</programlisting>
- </figure>
-
- <para>Note the first two bytes are <literal>0xeb</literal> and
- <literal>0xe</literal>. In the IA-32 architecture, these two
- bytes are interpreted as a relative jump past the header into
- the entry point, so in theory, <filename>boot1</filename> could
- jump here (address <literal>0x9000</literal>) instead of address
- <literal>0x9010</literal>. Note that the last field in the
- <acronym>BTX</acronym> header is a pointer to the client's
- (<filename>boot2</filename>) entry point. This field is patched
- at link time.</para>
-
- <para>Immediately following the header is the
- <acronym>BTX</acronym> server's entry point:</para>
-
- <figure xml:id="btx-init">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Initialization routine.
- */
-init: cli # Disable interrupts
- xor %ax,%ax # Zero/segment
- mov %ax,%ss # Set up
- mov $0x1800,%sp # stack
- mov %ax,%es # Address
- mov %ax,%ds # data
- pushl $0x2 # Clear
- popfl # flags</programlisting>
- </figure>
-
- <para>This code disables interrupts, sets up a working stack
- (starting at address <literal>0x1800</literal>) and clears the
- flags in the EFLAGS register. Note that the
- <literal>popfl</literal> instruction pops out a doubleword (4
- bytes) from the stack and places it in the EFLAGS register.
- As the value actually popped is <literal>2</literal>, the
- EFLAGS register is effectively cleared (IA-32 requires that bit
- 2 of the EFLAGS register always be 1).</para>
-
- <para>Our next code block clears (sets to <literal>0</literal>)
- the memory range <literal>0x5e00-0x8fff</literal>. This range
- is where the various data structures will be created:</para>
-
- <figure xml:id="btx-clear-mem">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Initialize memory.
- */
- mov $0x5e00,%di # Memory to initialize
- mov $(0x9000-0x5e00)/2,%cx # Words to zero
- rep # Zero-fill
- stosw # memory</programlisting>
- </figure>
-
- <para>Recall that <filename>boot1</filename> was originally loaded
- to address <literal>0x7c00</literal>, so, with this memory
- initialization, that copy effectively disappeared. However,
- also recall that <filename>boot1</filename> was relocated to
- <literal>0x700</literal>, so <emphasis>that</emphasis> copy is
- still in memory, and the <acronym>BTX</acronym> server will make
- use of it.</para>
-
- <para>Next, the real-mode <acronym>IVT</acronym> (Interrupt Vector
- Table is updated. The <acronym>IVT</acronym> is an array of
- segment/offset pairs for exception and interrupt handlers. The
- <acronym>BIOS</acronym> normally maps hardware interrupts to
- interrupt vectors <literal>0x8</literal> to
- <literal>0xf</literal> and <literal>0x70</literal> to
- <literal>0x77</literal> but, as will be seen, the 8259A
- Programmable Interrupt Controller, the chip controlling the
- actual mapping of hardware interrupts to interrupt vectors, is
- programmed to remap these interrupt vectors from
- <literal>0x8-0xf</literal> to <literal>0x20-0x27</literal> and
- from <literal>0x70-0x77</literal> to
- <literal>0x28-0x2f</literal>. Thus, interrupt handlers are
- provided for interrupt vectors <literal>0x20-0x2f</literal>.
- The reason the <acronym>BIOS</acronym>-provided handlers are not
- used directly is because they work in 16-bit real mode, but not
- 32-bit protected mode. Processor mode will be switched to
- 32-bit protected mode shortly. However, the
- <acronym>BTX</acronym> server sets up a mechanism to effectively
- use the handlers provided by the <acronym>BIOS</acronym>:</para>
-
- <figure xml:id="btx-ivt">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Update real mode IDT for reflecting hardware interrupts.
- */
- mov $intr20,%bx # Address first handler
- mov $0x10,%cx # Number of handlers
- mov $0x20*4,%di # First real mode IDT entry
-init.0: mov %bx,(%di) # Store IP
- inc %di # Address next
- inc %di # entry
- stosw # Store CS
- add $4,%bx # Next handler
- loop init.0 # Next IRQ</programlisting>
- </figure>
-
- <para>The next block creates the <acronym>IDT</acronym> (Interrupt
- Descriptor Table). The <acronym>IDT</acronym> is analogous, in
- protected mode, to the <acronym>IVT</acronym> in real mode.
- That is, the <acronym>IDT</acronym> describes the various
- exception and interrupt handlers used when the processor is
- executing in protected mode. In essence, it also consists of an
- array of segment/offset pairs, although the structure is
- somewhat more complex, because segments in protected mode are
- different than in real mode, and various protection mechanisms
- apply:</para>
-
- <figure xml:id="btx-idt">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Create IDT.
- */
- mov $0x5e00,%di # IDT's address
- mov $idtctl,%si # Control string
-init.1: lodsb # Get entry
- cbw # count
- xchg %ax,%cx # as word
- jcxz init.4 # If done
- lodsb # Get segment
- xchg %ax,%dx # P:DPL:type
- lodsw # Get control
- xchg %ax,%bx # set
- lodsw # Get handler offset
- mov $SEL_SCODE,%dh # Segment selector
-init.2: shr %bx # Handle this int?
- jnc init.3 # No
- mov %ax,(%di) # Set handler offset
- mov %dh,0x2(%di) # and selector
- mov %dl,0x5(%di) # Set P:DPL:type
- add $0x4,%ax # Next handler
-init.3: lea 0x8(%di),%di # Next entry
- loop init.2 # Till set done
- jmp init.1 # Continue</programlisting>
- </figure>
-
- <para>Each entry in the <literal>IDT</literal> is 8 bytes long.
- Besides the segment/offset information, they also describe the
- segment type, privilege level, and whether the segment is
- present in memory or not. The construction is such that
- interrupt vectors from <literal>0</literal> to
- <literal>0xf</literal> (exceptions) are handled by function
- <literal>intx00</literal>; vector <literal>0x10</literal> (also
- an exception) is handled by <literal>intx10</literal>; hardware
- interrupts, which are later configured to start at interrupt
- vector <literal>0x20</literal> all the way to interrupt vector
- <literal>0x2f</literal>, are handled by function
- <literal>intx20</literal>. Lastly, interrupt vector
- <literal>0x30</literal>, which is used for system calls, is
- handled by <literal>intx30</literal>, and vectors
- <literal>0x31</literal> and <literal>0x32</literal> are handled
- by <literal>intx31</literal>. It must be noted that only
- descriptors for interrupt vectors <literal>0x30</literal>,
- <literal>0x31</literal> and <literal>0x32</literal> are given
- privilege level 3, the same privilege level as the
- <filename>boot2</filename> client, which means the client can
- execute a software-generated interrupt to this vectors through
- the <literal>int</literal> instruction without failing (this is
- the way <filename>boot2</filename> use the services provided by
- the <acronym>BTX</acronym> server). Also, note that
- <emphasis>only</emphasis> software-generated interrupts are
- protected from code executing in lesser privilege levels.
- Hardware-generated interrupts and processor-generated exceptions
- are <emphasis>always</emphasis> handled adequately, regardless
- of the actual privileges involved.</para>
-
- <para>The next step is to initialize the <acronym>TSS</acronym>
- (Task-State Segment). The <acronym>TSS</acronym> is a hardware
- feature that helps the operating system or executive software
- implement multitasking functionality through process
- abstraction. The IA-32 architecture demands the creation and
- use of <emphasis>at least</emphasis> one <acronym>TSS</acronym>
- if multitasking facilities are used or different privilege
- levels are defined. Since the <filename>boot2</filename>
- client is executed in privilege level 3, but the
- <acronym>BTX</acronym> server runs in privilege level 0, a
- <acronym>TSS</acronym> must be defined:</para>
-
- <figure xml:id="btx-tss">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Initialize TSS.
- */
-init.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0
- movb $SEL_SDATA,TSS_SS0(%di) # Set SS0
- movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base</programlisting>
- </figure>
-
- <para>Note that a value is given for the Privilege Level 0 stack
- pointer and stack segment in the <acronym>TSS</acronym>. This
- is needed because, if an interrupt or exception is received
- while executing <filename>boot2</filename> in Privilege Level 3,
- a change to Privilege Level 0 is automatically performed by the
- processor, so a new working stack is needed. Finally, the I/O
- Map Base Address field of the <acronym>TSS</acronym> is given a
- value, which is a 16-bit offset from the beginning of the
- <acronym>TSS</acronym> to the I/O Permission Bitmap and the
- Interrupt Redirection Bitmap.</para>
-
- <para>After the <acronym>IDT</acronym> and <acronym>TSS</acronym>
- are created, the processor is ready to switch to protected mode.
- This is done in the next block:</para>
-
- <figure xml:id="btx-prot">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Bring up the system.
- */
- mov $0x2820,%bx # Set protected mode
- callw setpic # IRQ offsets
- lidt idtdesc # Set IDT
- lgdt gdtdesc # Set GDT
- mov %cr0,%eax # Switch to protected
- inc %ax # mode
- mov %eax,%cr0 #
- ljmp $SEL_SCODE,$init.8 # To 32-bit code
- .code32
-init.8: xorl %ecx,%ecx # Zero
- movb $SEL_SDATA,%cl # To 32-bit
- movw %cx,%ss # stack</programlisting>
- </figure>
-
- <para>First, a call is made to <literal>setpic</literal> to
- program the 8259A <acronym>PIC</acronym> (Programmable Interrupt
- Controller). This chip is connected to multiple hardware
- interrupt sources. Upon receiving an interrupt from a device,
- it signals the processor with the appropriate interrupt vector.
- This can be customized so that specific interrupts are
- associated with specific interrupt vectors, as explained before.
- Next, the <acronym>IDTR</acronym> (Interrupt Descriptor Table
- Register) and <acronym>GDTR</acronym> (Global Descriptor Table
- Register) are loaded with the instructions
- <literal>lidt</literal> and <literal>lgdt</literal>,
- respectively. These registers are loaded with the base address
- and limit address for the <acronym>IDT</acronym> and
- <acronym>GDT</acronym>. The following three instructions set
- the Protection Enable (PE) bit of the <literal>%cr0</literal>
- register. This effectively switches the processor to 32-bit
- protected mode. Next, a long jump is made to
- <literal>init.8</literal> using segment selector SEL_SCODE,
- which selects the Supervisor Code Segment. The processor is
- effectively executing in CPL 0, the most privileged level, after
- this jump. Finally, the Supervisor Data Segment is selected for
- the stack by assigning the segment selector SEL_SDATA to the
- <literal>%ss</literal> register. This data segment also has a
- privilege level of <literal>0</literal>.</para>
-
- <para>Our last code block is responsible for loading the
- <acronym>TR</acronym> (Task Register) with the segment selector
- for the <acronym>TSS</acronym> we created earlier, and setting
- the User Mode environment before passing execution control to
- the <filename>boot2</filename> client.</para>
-
- <figure xml:id="btx-end">
- <title><filename>sys/boot/i386/btx/btx/btx.S</filename></title>
-
- <programlisting>/*
- * Launch user task.
- */
- movb $SEL_TSS,%cl # Set task
- ltr %cx # register
- movl $0xa000,%edx # User base address
- movzwl %ss:BDA_MEM,%eax # Get free memory
- shll $0xa,%eax # To bytes
- subl $ARGSPACE,%eax # Less arg space
- subl %edx,%eax # Less base
- movb $SEL_UDATA,%cl # User data selector
- pushl %ecx # Set SS
- pushl %eax # Set ESP
- push $0x202 # Set flags (IF set)
- push $SEL_UCODE # Set CS
- pushl btx_hdr+0xc # Set EIP
- pushl %ecx # Set GS
- pushl %ecx # Set FS
- pushl %ecx # Set DS
- pushl %ecx # Set ES
- pushl %edx # Set EAX
- movb $0x7,%cl # Set remaining
-init.9: push $0x0 # general
- loop init.9 # registers
- popa # and initialize
- popl %es # Initialize
- popl %ds # user
- popl %fs # segment
- popl %gs # registers
- iret # To user mode</programlisting>
- </figure>
-
- <para>Note that the client's environment include a stack segment
- selector and stack pointer (registers <literal>%ss</literal> and
- <literal>%esp</literal>). Indeed, once the
- <acronym>TR</acronym> is loaded with the appropriate stack
- segment selector (instruction <literal>ltr</literal>), the stack
- pointer is calculated and pushed onto the stack along with the
- stack's segment selector. Next, the value
- <literal>0x202</literal> is pushed onto the stack; it is the
- value that the EFLAGS will get when control is passed to the
- client. Also, the User Mode code segment selector and the
- client's entry point are pushed. Recall that this entry
- point is patched in the <acronym>BTX</acronym> header at link
- time. Finally, segment selectors (stored in register
- <literal>%ecx</literal>) for the segment registers
- <literal>%gs, %fs, %ds and %es</literal> are pushed onto the
- stack, along with the value at <literal>%edx</literal>
- (<literal>0xa000</literal>). Keep in mind the various values
- that have been pushed onto the stack (they will be popped out
- shortly). Next, values for the remaining general purpose
- registers are also pushed onto the stack (note the
- <literal>loop</literal> that pushes the value
- <literal>0</literal> seven times). Now, values will be started
- to be popped out of the stack. First, the
- <literal>popa</literal> instruction pops out of the stack the
- latest seven values pushed. They are stored in the general
- purpose registers in order
- <literal>%edi, %esi, %ebp, %ebx, %edx, %ecx, %eax</literal>.
- Then, the various segment selectors pushed are popped into the
- various segment registers. Five values still remain on the
- stack. They are popped when the <literal>iret</literal>
- instruction is executed. This instruction first pops
- the value that was pushed from the <acronym>BTX</acronym>
- header. This value is a pointer to <filename>boot2</filename>'s
- entry point. It is placed in the register
- <literal>%eip</literal>, the instruction pointer register.
- Next, the segment selector for the User Code Segment is popped
- and copied to register <literal>%cs</literal>. Remember that
- this segment's privilege level is 3, the least privileged
- level. This means that we must provide values for the stack of
- this privilege level. This is why the processor, besides
- further popping the value for the EFLAGS register, does two more
- pops out of the stack. These values go to the stack
- pointer (<literal>%esp</literal>) and the stack segment
- (<literal>%ss</literal>). Now, execution continues at
- <literal>boot0</literal>'s entry point.</para>
-
- <para>It is important to note how the User Code Segment is
- defined. This segment's <emphasis>base address</emphasis> is
- set to <literal>0xa000</literal>. This means that code memory
- addresses are <emphasis>relative</emphasis> to address 0xa000;
- if code being executed is fetched from address
- <literal>0x2000</literal>, the <emphasis>actual</emphasis>
- memory addressed is
- <literal>0xa000+0x2000=0xc000</literal>.</para>
- </sect1>
-
- <sect1 xml:id="boot2">
- <title><application>boot2</application> Stage</title>
-
- <para><literal>boot2</literal> defines an important structure,
- <literal>struct bootinfo</literal>. This structure is
- initialized by <literal>boot2</literal> and passed to the
- loader, and then further to the kernel. Some nodes of this
- structures are set by <literal>boot2</literal>, the rest by the
- loader. This structure, among other information, contains the
- kernel filename, <acronym>BIOS</acronym> harddisk geometry,
- <acronym>BIOS</acronym> drive number for boot device, physical
- memory available, <literal>envp</literal> pointer etc. The
- definition for it is:</para>
-
- <programlisting><filename>/usr/include/machine/bootinfo.h:</filename>
-struct bootinfo {
- u_int32_t bi_version;
- u_int32_t bi_kernelname; /* represents a char * */
- u_int32_t bi_nfs_diskless; /* struct nfs_diskless * */
- /* End of fields that are always present. */
-#define bi_endcommon bi_n_bios_used
- u_int32_t bi_n_bios_used;
- u_int32_t bi_bios_geom[N_BIOS_GEOM];
- u_int32_t bi_size;
- u_int8_t bi_memsizes_valid;
- u_int8_t bi_bios_dev; /* bootdev BIOS unit number */
- u_int8_t bi_pad[2];
- u_int32_t bi_basemem;
- u_int32_t bi_extmem;
- u_int32_t bi_symtab; /* struct symtab * */
- u_int32_t bi_esymtab; /* struct symtab * */
- /* Items below only from advanced bootloader */
- u_int32_t bi_kernend; /* end of kernel space */
- u_int32_t bi_envp; /* environment */
- u_int32_t bi_modulep; /* preloaded modules */
-};</programlisting>
-
- <para><literal>boot2</literal> enters into an infinite loop
- waiting for user input, then calls <function>load()</function>.
- If the user does not press anything, the loop breaks by a
- timeout, so <function>load()</function> will load the default
- file (<filename>/boot/loader</filename>). Functions
- <function>ino_t lookup(char *filename)</function> and
- <function>int xfsread(ino_t inode, void *buf, size_t
- nbyte)</function> are used to read the content of a file into
- memory. <filename>/boot/loader</filename> is an
- <acronym>ELF</acronym> binary, but where the
- <acronym>ELF</acronym> header is prepended with
- <filename>a.out</filename>'s <literal>struct
- exec</literal> structure. <function>load()</function> scans the
- loader's ELF header, loading the content of
- <filename>/boot/loader</filename> into memory, and passing the
- execution to the loader's entry:</para>
-
- <programlisting><filename>sys/boot/i386/boot2/boot2.c:</filename>
- __exec((caddr_t)addr, RB_BOOTINFO | (opts &amp; RBX_MASK),
- MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
- 0, 0, 0, VTOP(&amp;bootinfo));</programlisting>
- </sect1>
-
- <sect1 xml:id="boot-loader">
- <title><application>loader</application> Stage</title>
-
- <para><application>loader</application> is a
- <acronym>BTX</acronym> client as well. I will not describe it
- here in detail, there is a comprehensive man page written by
- Mike Smith, &man.loader.8;. The underlying mechanisms and
- <acronym>BTX</acronym> were discussed above.</para>
-
- <para>The main task for the loader is to boot the kernel. When
- the kernel is loaded into memory, it is being called by the
- loader:</para>
-
- <programlisting><filename>sys/boot/common/boot.c:</filename>
- /* Call the exec handler from the loader matching the kernel */
- module_formats[km-&gt;m_loader]-&gt;l_exec(km);</programlisting>
- </sect1>
-
- <sect1 xml:id="boot-kernel">
- <title>Kernel Initialization</title>
-
- <para>Let us take a look at the command that links the kernel.
- This will help identify the exact location where the loader
- passes execution to the kernel. This location is the kernel's
- actual entry point.</para>
-
- <programlisting><filename>sys/conf/Makefile.i386:</filename>
-ld -elf -Bdynamic -T /usr/src/sys/conf/ldscript.i386 -export-dynamic \
--dynamic-linker /red/herring -o kernel -X locore.o \
-&lt;lots of kernel .o files&gt;</programlisting>
-
- <indexterm><primary>ELF</primary></indexterm>
- <para>A few interesting things can be seen here. First, the
- kernel is an ELF dynamically linked binary, but the dynamic
- linker for kernel is <filename>/red/herring</filename>, which is
- definitely a bogus file. Second, taking a look at the file
- <filename>sys/conf/ldscript.i386</filename> gives an idea about
- what <application>ld</application> options are used when
- compiling a kernel. Reading through the first few lines, the
- string</para>
-
- <programlisting><filename>sys/conf/ldscript.i386:</filename>
-ENTRY(btext)</programlisting>
-
- <para>says that a kernel's entry point is the symbol `btext'.
- This symbol is defined in <filename>locore.s</filename>:</para>
-
- <programlisting><filename>sys/i386/i386/locore.s:</filename>
- .text
-/**********************************************************************
- *
- * This is where the bootblocks start us, set the ball rolling...
- *
- */
-NON_GPROF_ENTRY(btext)</programlisting>
-
- <para>First, the register EFLAGS is set to a predefined value of
- 0x00000002. Then all the segment registers are
- initialized:</para>
-
- <programlisting><filename>sys/i386/i386/locore.s:</filename>
-/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_KERNEL
- popfl
-
-/*
- * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap
- * to set %cs, %ds, %es and %ss.
- */
- mov %ds, %ax
- mov %ax, %fs
- mov %ax, %gs</programlisting>
-
- <para>btext calls the routines
- <function>recover_bootinfo()</function>,
- <function>identify_cpu()</function>,
- <function>create_pagetables()</function>, which are also defined
- in <filename>locore.s</filename>. Here is a description of what
- they do:</para>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="2" align="left">
- <tbody>
- <row>
- <entry><function>recover_bootinfo</function></entry>
- <entry>This routine parses the parameters to the kernel
- passed from the bootstrap. The kernel may have been
- booted in 3 ways: by the loader, described above, by the
- old disk boot blocks, or by the old diskless boot
- procedure. This function determines the booting method,
- and stores the <literal>struct bootinfo</literal>
- structure into the kernel memory.</entry>
- </row>
-
- <row>
- <entry><function>identify_cpu</function></entry>
- <entry>This functions tries to find out what CPU it is
- running on, storing the value found in a variable
- <varname>_cpu</varname>.</entry>
- </row>
-
- <row>
- <entry><function>create_pagetables</function></entry>
- <entry>This function allocates and fills out a Page Table
- Directory at the top of the kernel memory area.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>The next steps are enabling VME, if the CPU supports
- it:</para>
-
- <programlisting> testl $CPUID_VME, R(_cpu_feature)
- jz 1f
- movl %cr4, %eax
- orl $CR4_VME, %eax
- movl %eax, %cr4</programlisting>
-
- <para>Then, enabling paging:</para>
-
- <programlisting>/* Now enable paging */
- movl R(_IdlePTD), %eax
- movl %eax,%cr3 /* load ptd addr into mmu */
- movl %cr0,%eax /* get control word */
- orl $CR0_PE|CR0_PG,%eax /* enable paging */
- movl %eax,%cr0 /* and let's page NOW! */</programlisting>
-
- <para>The next three lines of code are because the paging was set,
- so the jump is needed to continue the execution in virtualized
- address space:</para>
-
- <programlisting> pushl $begin /* jump to high virtualized address */
- ret
-
-/* now running relocated at KERNBASE where the system is linked to run */
-begin:</programlisting>
-
- <para>The function <function>init386()</function> is called with
- a pointer to the first free physical page, after that
- <function>mi_startup()</function>. <function>init386</function>
- is an architecture dependent initialization function, and
- <function>mi_startup()</function> is an architecture independent
- one (the 'mi_' prefix stands for Machine Independent). The
- kernel never returns from <function>mi_startup()</function>, and
- by calling it, the kernel finishes booting:</para>
-
- <programlisting><filename>sys/i386/i386/locore.s:</filename>
- movl physfree, %esi
- pushl %esi /* value of first for init386(first) */
- call _init386 /* wire 386 chip for unix operation */
- call _mi_startup /* autoconfiguration, mountroot etc */
- hlt /* never returns to here */</programlisting>
-
- <sect2>
- <title><function>init386()</function></title>
-
- <para><function>init386()</function> is defined in
- <filename>sys/i386/i386/machdep.c</filename> and performs
- low-level initialization specific to the i386 chip. The
- switch to protected mode was performed by the loader. The
- loader has created the very first task, in which the kernel
- continues to operate. Before looking at the code, consider
- the tasks the processor must complete to initialize protected
- mode execution:</para>
-
- <itemizedlist>
- <listitem>
- <para>Initialize the kernel tunable parameters, passed from
- the bootstrapping program.</para>
- </listitem>
-
- <listitem>
- <para>Prepare the GDT.</para>
- </listitem>
-
- <listitem>
- <para>Prepare the IDT.</para>
- </listitem>
-
- <listitem>
- <para>Initialize the system console.</para>
- </listitem>
-
- <listitem>
- <para>Initialize the DDB, if it is compiled into
- kernel.</para>
- </listitem>
-
- <listitem>
- <para>Initialize the TSS.</para>
- </listitem>
-
- <listitem>
- <para>Prepare the LDT.</para>
- </listitem>
-
- <listitem>
- <para>Set up proc0's pcb.</para>
- </listitem>
- </itemizedlist>
-
- <indexterm><primary>parameters</primary></indexterm>
- <para><function>init386()</function> initializes the tunable
- parameters passed from bootstrap by setting the environment
- pointer (envp) and calling <function>init_param1()</function>.
- The envp pointer has been passed from loader in the
- <literal>bootinfo</literal> structure:</para>
-
- <programlisting><filename>sys/i386/i386/machdep.c:</filename>
- kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
-
- /* Init basic tunables, hz etc */
- init_param1();</programlisting>
-
- <para><function>init_param1()</function> is defined in
- <filename>sys/kern/subr_param.c</filename>. That file has a
- number of sysctls, and two functions,
- <function>init_param1()</function> and
- <function>init_param2()</function>, that are called from
- <function>init386()</function>:</para>
-
- <programlisting><filename>sys/kern/subr_param.c:</filename>
- hz = HZ;
- TUNABLE_INT_FETCH("kern.hz", &amp;hz);</programlisting>
-
- <para>TUNABLE_&lt;typename&gt;_FETCH is used to fetch the value
- from the environment:</para>
-
- <programlisting><filename>/usr/src/sys/sys/kernel.h:</filename>
-#define TUNABLE_INT_FETCH(path, var) getenv_int((path), (var))</programlisting>
-
- <para>Sysctl <literal>kern.hz</literal> is the system clock
- tick. Additionally, these sysctls are set by
- <function>init_param1()</function>: <literal>kern.maxswzone,
- kern.maxbcache, kern.maxtsiz, kern.dfldsiz, kern.maxdsiz,
- kern.dflssiz, kern.maxssiz, kern.sgrowsiz</literal>.</para>
-
- <indexterm>
- <primary>Global Descriptors Table (GDT)</primary>
- </indexterm>
-
- <para>Then <function>init386()</function> prepares the Global
- Descriptors Table (GDT). Every task on an x86 is running in
- its own virtual address space, and this space is addressed by
- a segment:offset pair. Say, for instance, the current
- instruction to be executed by the processor lies at CS:EIP,
- then the linear virtual address for that instruction would be
- <quote>the virtual address of code segment CS</quote> + EIP.
- For convenience, segments begin at virtual address 0 and end
- at a 4Gb boundary. Therefore, the instruction's linear
- virtual address for this example would just be the value of
- EIP. Segment registers such as CS, DS etc are the selectors,
- i.e., indexes, into GDT (to be more precise, an index is not a
- selector itself, but the INDEX field of a selector).
- FreeBSD's GDT holds descriptors for 15 selectors per
- CPU:</para>
-
- <programlisting><filename>sys/i386/i386/machdep.c:</filename>
-union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */
-
-<filename>sys/i386/include/segments.h:</filename>
-/*
- * Entries in the Global Descriptor Table (GDT)
- */
-#define GNULL_SEL 0 /* Null Descriptor */
-#define GCODE_SEL 1 /* Kernel Code Descriptor */
-#define GDATA_SEL 2 /* Kernel Data Descriptor */
-#define GPRIV_SEL 3 /* SMP Per-Processor Private Data */
-#define GPROC0_SEL 4 /* Task state process slot zero and up */
-#define GLDT_SEL 5 /* LDT - eventually one per process */
-#define GUSERLDT_SEL 6 /* User LDT */
-#define GTGATE_SEL 7 /* Process task switch gate */
-#define GBIOSLOWMEM_SEL 8 /* BIOS low memory access (must be entry 8) */
-#define GPANIC_SEL 9 /* Task state to consider panic from */
-#define GBIOSCODE32_SEL 10 /* BIOS interface (32bit Code) */
-#define GBIOSCODE16_SEL 11 /* BIOS interface (16bit Code) */
-#define GBIOSDATA_SEL 12 /* BIOS interface (Data) */
-#define GBIOSUTIL_SEL 13 /* BIOS interface (Utility) */
-#define GBIOSARGS_SEL 14 /* BIOS interface (Arguments) */</programlisting>
-
- <para>Note that those #defines are not selectors themselves, but
- just a field INDEX of a selector, so they are exactly the
- indices of the GDT. for example, an actual selector for the
- kernel code (GCODE_SEL) has the value 0x08.</para>
-
- <indexterm><primary>Interrupt Descriptor Table
- (IDT)</primary></indexterm>
- <para>The next step is to initialize the Interrupt Descriptor
- Table (IDT). This table is referenced by the processor when a
- software or hardware interrupt occurs. For example, to make a
- system call, user application issues the
- <literal>INT 0x80</literal> instruction. This is a software
- interrupt, so the processor's hardware looks up a record with
- index 0x80 in the IDT. This record points to the routine that
- handles this interrupt, in this particular case, this will be
- the kernel's syscall gate. The IDT may have a maximum of 256
- (0x100) records. The kernel allocates NIDT records for the
- IDT, where NIDT is the maximum (256):</para>
-
- <programlisting><filename>sys/i386/i386/machdep.c:</filename>
-static struct gate_descriptor idt0[NIDT];
-struct gate_descriptor *idt = &amp;idt0[0]; /* interrupt descriptor table */</programlisting>
-
- <para>For each interrupt, an appropriate handler is set. The
- syscall gate for <literal>INT 0x80</literal> is set as
- well:</para>
-
- <programlisting><filename>sys/i386/i386/machdep.c:</filename>
- setidt(0x80, &amp;IDTVEC(int0x80_syscall),
- SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));</programlisting>
-
- <para>So when a userland application issues the
- <literal>INT 0x80</literal> instruction, control will transfer
- to the function <function>_Xint0x80_syscall</function>, which
- is in the kernel code segment and will be executed with
- supervisor privileges.</para>
-
- <para>Console and DDB are then initialized:</para>
- <indexterm><primary>DDB</primary></indexterm>
-
- <programlisting><filename>sys/i386/i386/machdep.c:</filename>
- cninit();
-/* skipped */
-#ifdef DDB
- kdb_init();
- if (boothowto &amp; RB_KDB)
- Debugger("Boot flags requested debugger");
-#endif</programlisting>
-
- <para>The Task State Segment is another x86 protected mode
- structure, the TSS is used by the hardware to store task
- information when a task switch occurs.</para>
-
- <para>The Local Descriptors Table is used to reference userland
- code and data. Several selectors are defined to point to the
- LDT, they are the system call gates and the user code and data
- selectors:</para>
-
- <programlisting><filename>/usr/include/machine/segments.h:</filename>
-#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
-#define LSYS5SIGR_SEL 1
-#define L43BSDCALLS_SEL 2 /* notyet */
-#define LUCODE_SEL 3
-#define LSOL26CALLS_SEL 4 /* Solaris &gt;= 2.6 system call gate */
-#define LUDATA_SEL 5
-/* separate stack, es,fs,gs sels ? */
-/* #define LPOSIXCALLS_SEL 5*/ /* notyet */
-#define LBSDICALLS_SEL 16 /* BSDI system call gate */
-#define NLDT (LBSDICALLS_SEL + 1)</programlisting>
-
- <para>Next, proc0's Process Control Block
- (<literal>struct pcb</literal>) structure is initialized.
- proc0 is a <literal>struct proc</literal> structure that
- describes a kernel process. It is always present while the
- kernel is running, therefore it is declared as global:</para>
-
- <programlisting><filename>sys/kern/kern_init.c:</filename>
- struct proc proc0;</programlisting>
-
- <para>The structure <literal>struct pcb</literal> is a part of a
- proc structure. It is defined in
- <filename>/usr/include/machine/pcb.h</filename> and has a
- process's information specific to the i386 architecture, such
- as registers values.</para>
- </sect2>
-
- <sect2>
- <title><function>mi_startup()</function></title>
-
- <para>This function performs a bubble sort of all the system
- initialization objects and then calls the entry of each object
- one by one:</para>
-
- <programlisting><filename>sys/kern/init_main.c:</filename>
- for (sipp = sysinit; *sipp; sipp++) {
-
- /* ... skipped ... */
-
- /* Call function */
- (*((*sipp)-&gt;func))((*sipp)-&gt;udata);
- /* ... skipped ... */
- }</programlisting>
-
- <para>Although the sysinit framework is described in the <link
- xlink:href="&url.doc.langbase;/books/developers-handbook">Developers'
- Handbook</link>, I will discuss the internals of it.</para>
-
- <indexterm><primary>sysinit objects</primary></indexterm>
- <para>Every system initialization object (sysinit object) is
- created by calling a SYSINIT() macro. Let us take as example
- an <literal>announce</literal> sysinit object. This object
- prints the copyright message:</para>
-
- <programlisting><filename>sys/kern/init_main.c:</filename>
-static void
-print_caddr_t(void *data __unused)
-{
- printf("%s", (char *)data);
-}
-SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)</programlisting>
-
- <para>The subsystem ID for this object is SI_SUB_COPYRIGHT
- (0x0800001), which comes right after the SI_SUB_CONSOLE
- (0x0800000). So, the copyright message will be printed out
- first, just after the console initialization.</para>
-
- <para>Let us take a look at what exactly the macro
- <literal>SYSINIT()</literal> does. It expands to a
- <literal>C_SYSINIT()</literal> macro. The
- <literal>C_SYSINIT()</literal> macro then expands to a static
- <literal>struct sysinit</literal> structure declaration with
- another <literal>DATA_SET</literal> macro call:</para>
-
- <programlisting><filename>/usr/include/sys/kernel.h:</filename>
- #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \
- static struct sysinit uniquifier ## _sys_init = { \ subsystem, \
- order, \ func, \ ident \ }; \ DATA_SET(sysinit_set,uniquifier ##
- _sys_init);
-
-#define SYSINIT(uniquifier, subsystem, order, func, ident) \
- C_SYSINIT(uniquifier, subsystem, order, \
- (sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)ident)</programlisting>
-
- <para>The <literal>DATA_SET()</literal> macro expands to a
- <literal>MAKE_SET()</literal>, and that macro is the point
- where all the sysinit magic is hidden:</para>
-
- <programlisting><filename>/usr/include/linker_set.h:</filename>
-#define MAKE_SET(set, sym) \
- static void const * const __set_##set##_sym_##sym = &amp;sym; \
- __asm(".section .set." #set ",\"aw\""); \
- __asm(".long " #sym); \
- __asm(".previous")
-#endif
-#define TEXT_SET(set, sym) MAKE_SET(set, sym)
-#define DATA_SET(set, sym) MAKE_SET(set, sym)</programlisting>
-
- <para>In our case, the following declaration will occur:</para>
-
- <programlisting>static struct sysinit announce_sys_init = {
- SI_SUB_COPYRIGHT,
- SI_ORDER_FIRST,
- (sysinit_cfunc_t)(sysinit_nfunc_t) print_caddr_t,
- (void *) copyright
-};
-
-static void const *const __set_sysinit_set_sym_announce_sys_init =
- &amp;announce_sys_init;
-__asm(".section .set.sysinit_set" ",\"aw\"");
-__asm(".long " "announce_sys_init");
-__asm(".previous");</programlisting>
-
- <para>The first <literal>__asm</literal> instruction will create
- an ELF section within the kernel's executable. This will
- happen at kernel link time. The section will have the name
- <literal>.set.sysinit_set</literal>. The content of this
- section is one 32-bit value, the address of announce_sys_init
- structure, and that is what the second
- <literal>__asm</literal> is. The third
- <literal>__asm</literal> instruction marks the end of a
- section. If a directive with the same section name occurred
- before, the content, i.e., the 32-bit value, will be appended
- to the existing section, so forming an array of 32-bit
- pointers.</para>
-
- <para>Running <application>objdump</application> on a kernel
- binary, you may notice the presence of such small
- sections:</para>
-
- <screen>&prompt.user; <userinput>objdump -h /kernel</userinput>
- 7 .set.cons_set 00000014 c03164c0 c03164c0 002154c0 2**2
- CONTENTS, ALLOC, LOAD, DATA
- 8 .set.kbddriver_set 00000010 c03164d4 c03164d4 002154d4 2**2
- CONTENTS, ALLOC, LOAD, DATA
- 9 .set.scrndr_set 00000024 c03164e4 c03164e4 002154e4 2**2
- CONTENTS, ALLOC, LOAD, DATA
- 10 .set.scterm_set 0000000c c0316508 c0316508 00215508 2**2
- CONTENTS, ALLOC, LOAD, DATA
- 11 .set.sysctl_set 0000097c c0316514 c0316514 00215514 2**2
- CONTENTS, ALLOC, LOAD, DATA
- 12 .set.sysinit_set 00000664 c0316e90 c0316e90 00215e90 2**2
- CONTENTS, ALLOC, LOAD, DATA</screen>
-
- <para>This screen dump shows that the size of .set.sysinit_set
- section is 0x664 bytes, so <literal>0x664/sizeof(void
- *)</literal> sysinit objects are compiled into the kernel.
- The other sections such as <literal>.set.sysctl_set</literal>
- represent other linker sets.</para>
-
- <para>By defining a variable of type <literal>struct
- linker_set</literal> the content of
- <literal>.set.sysinit_set</literal> section will be
- <quote>collected</quote> into that variable:</para>
-
- <programlisting><filename>sys/kern/init_main.c:</filename>
- extern struct linker_set sysinit_set; /* XXX */</programlisting>
-
- <para>The <literal>struct linker_set</literal> is defined as
- follows:</para>
-
- <programlisting><filename>/usr/include/linker_set.h:</filename>
- struct linker_set {
- int ls_length;
- void *ls_items[1]; /* really ls_length of them, trailing NULL */
-};</programlisting>
-
- <para>The first node will be equal to the number of a sysinit
- objects, and the second node will be a NULL-terminated array
- of pointers to them.</para>
-
- <para>Returning to the <function>mi_startup()</function>
- discussion, it is must be clear now, how the sysinit objects
- are being organized. The <function>mi_startup()</function>
- function sorts them and calls each. The very last object is
- the system scheduler:</para>
-
- <programlisting><filename>/usr/include/sys/kernel.h:</filename>
-enum sysinit_sub_id {
- SI_SUB_DUMMY = 0x0000000, /* not executed; for linker*/
- SI_SUB_DONE = 0x0000001, /* processed*/
- SI_SUB_CONSOLE = 0x0800000, /* console*/
- SI_SUB_COPYRIGHT = 0x0800001, /* first use of console*/
-...
- SI_SUB_RUN_SCHEDULER = 0xfffffff /* scheduler: no return*/
-};</programlisting>
-
- <para>The system scheduler sysinit object is defined in the file
- <filename>sys/vm/vm_glue.c</filename>, and the entry point for
- that object is <function>scheduler()</function>. That
- function is actually an infinite loop, and it represents a
- process with PID 0, the swapper process. The proc0 structure,
- mentioned before, is used to describe it.</para>
-
- <para>The first user process, called <emphasis>init</emphasis>,
- is created by the sysinit object
- <literal>init</literal>:</para>
-
- <programlisting><filename>sys/kern/init_main.c:</filename>
-static void
-create_init(const void *udata __unused)
-{
- int error;
- int s;
-
- s = splhigh();
- error = fork1(&amp;proc0, RFFDG | RFPROC, &amp;initproc);
- if (error)
- panic("cannot fork init: %d\n", error);
- initproc-&gt;p_flag |= P_INMEM | P_SYSTEM;
- cpu_set_fork_handler(initproc, start_init, NULL);
- remrunqueue(initproc);
- splx(s);
-}
-SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)</programlisting>
-
- <para>The <function>create_init()</function> allocates a new
- process by calling <function>fork1()</function>, but does not
- mark it runnable. When this new process is scheduled for
- execution by the scheduler, the
- <function>start_init()</function> will be called. That
- function is defined in <filename>init_main.c</filename>. It
- tries to load and exec the <filename>init</filename> binary,
- probing <filename>/sbin/init</filename> first, then
- <filename>/sbin/oinit</filename>,
- <filename>/sbin/init.bak</filename>, and finally
- <filename>/stand/sysinstall</filename>:</para>
-
- <programlisting><filename>sys/kern/init_main.c:</filename>
-static char init_path[MAXPATHLEN] =
-#ifdef INIT_PATH
- __XSTRING(INIT_PATH);
-#else
- "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall";
-#endif</programlisting>
- </sect2>
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/chapters.ent b/en_US.ISO8859-1/books/arch-handbook/chapters.ent
deleted file mode 100644
index 5182a6f8fb..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/chapters.ent
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- Creates entities for each chapter in the FreeBSD Architecture
- Handbook. Each entity is named chap.foo, where foo is the value
- of the id attribute on that chapter, and corresponds to the name of
- the directory in which that chapter's .xml file is stored.
-
- Chapters should be listed in the order in which they are referenced.
-
- $FreeBSD$
--->
-
-<!-- Part one - Kernel -->
-<!ENTITY chap.boot SYSTEM "boot/chapter.xml">
-<!ENTITY chap.kobj SYSTEM "kobj/chapter.xml">
-<!ENTITY chap.sysinit SYSTEM "sysinit/chapter.xml">
-<!ENTITY chap.locking SYSTEM "locking/chapter.xml">
-<!ENTITY chap.vm SYSTEM "vm/chapter.xml">
-<!ENTITY chap.jail SYSTEM "jail/chapter.xml">
-<!ENTITY chap.mac SYSTEM "mac/chapter.xml">
-<!ENTITY chap.smp SYSTEM "smp/chapter.xml">
-
-<!-- Part Two - Device Drivers -->
-<!ENTITY chap.driverbasics SYSTEM "driverbasics/chapter.xml">
-<!ENTITY chap.isa SYSTEM "isa/chapter.xml">
-<!ENTITY chap.pci SYSTEM "pci/chapter.xml">
-<!ENTITY chap.scsi SYSTEM "scsi/chapter.xml">
-<!ENTITY chap.usb SYSTEM "usb/chapter.xml">
-<!ENTITY chap.newbus SYSTEM "newbus/chapter.xml">
-<!ENTITY chap.snd SYSTEM "sound/chapter.xml">
-<!ENTITY chap.pccard SYSTEM "pccard/chapter.xml">
-
-<!-- Part three - Appendices -->
-<!ENTITY chap.index "<index xmlns='http://docbook.org/ns/docbook'/>">
diff --git a/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml
deleted file mode 100644
index 9826e3a1d9..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml
+++ /dev/null
@@ -1,423 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD$
--->
-
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:id="driverbasics">
-
- <info>
- <title>Writing FreeBSD Device Drivers</title>
-
- <authorgroup>
- <author>
- <personname>
- <firstname>Murray</firstname>
- <surname>Stokely</surname>
- </personname>
-
- <contrib>Written by </contrib>
- </author>
- </authorgroup>
-
- <authorgroup>
- <author>
- <personname>
- <firstname>J&ouml;rg</firstname>
- <surname>Wunsch</surname>
- </personname>
-
- <contrib>Based on intro(4) manual page by </contrib>
- </author>
- </authorgroup>
- </info>
-
- <sect1 xml:id="driverbasics-intro">
- <title>Introduction</title>
-
- <indexterm><primary>device driver</primary></indexterm>
- <indexterm><primary>pseudo-device</primary></indexterm>
-
- <para>This chapter provides a brief introduction to writing device
- drivers for FreeBSD. A device in this context is a term used
- mostly for hardware-related stuff that belongs to the system,
- like disks, printers, or a graphics display with its keyboard.
- A device driver is the software component of the operating
- system that controls a specific device. There are also
- so-called pseudo-devices where a device driver emulates the
- behavior of a device in software without any particular
- underlying hardware. Device drivers can be compiled into the
- system statically or loaded on demand through the dynamic kernel
- linker facility `kld'.</para>
-
- <indexterm><primary>device nodes</primary></indexterm>
-
- <para>Most devices in a &unix;-like operating system are accessed
- through device-nodes, sometimes also called special files.
- These files are usually located under the directory
- <filename>/dev</filename> in the filesystem hierarchy.</para>
-
- <para>Device drivers can roughly be broken down into two
- categories; character and network device drivers.</para>
-
- </sect1>
-
- <sect1 xml:id="driverbasics-kld">
- <title>Dynamic Kernel Linker Facility - KLD</title>
-
- <indexterm>
- <primary>kernel linking</primary>
- <secondary>dynamic</secondary>
- </indexterm>
- <indexterm>
- <primary>kernel loadable modules (KLD)</primary>
- </indexterm>
-
- <para>The kld interface allows system administrators to
- dynamically add and remove functionality from a running system.
- This allows device driver writers to load their new changes into
- a running kernel without constantly rebooting to test
- changes.</para>
-
- <indexterm>
- <primary>kernel modules</primary>
- <secondary>loading</secondary>
- </indexterm>
- <indexterm>
- <primary>kernel modules</primary>
- <secondary>unloading</secondary>
- </indexterm>
- <indexterm>
- <primary>kernel modules</primary>
- <secondary>listing</secondary>
- </indexterm>
-
- <para>The kld interface is used through:</para>
-
- <itemizedlist>
- <listitem>
- <simpara><command>kldload</command> - loads a new kernel
- module</simpara></listitem>
- <listitem>
- <simpara><command>kldunload</command> - unloads a kernel
- module</simpara></listitem>
- <listitem>
- <simpara><command>kldstat</command> - lists loaded
- modules</simpara></listitem>
- </itemizedlist>
-
- <para>Skeleton Layout of a kernel module</para>
-
- <programlisting>/*
- * KLD Skeleton
- * Inspired by Andrew Reiter's Daemonnews article
- */
-
-#include &lt;sys/types.h&gt;
-#include &lt;sys/module.h&gt;
-#include &lt;sys/systm.h&gt; /* uprintf */
-#include &lt;sys/errno.h&gt;
-#include &lt;sys/param.h&gt; /* defines used in kernel.h */
-#include &lt;sys/kernel.h&gt; /* 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 = EOPNOTSUPP;
- break;
- }
- return(err);
-}
-
-/* Declare this module to the rest of the kernel */
-
-static moduledata_t skel_mod = {
- "skel",
- skel_loader,
- NULL
-};
-
-DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);</programlisting>
-
-
- <sect2>
- <title>Makefile</title>
-
- <para>&os; provides a system makefile to simplify compiling a
- kernel module.</para>
-
- <programlisting>SRCS=skeleton.c
-KMOD=skeleton
-
-.include &lt;bsd.kmod.mk&gt;</programlisting>
-
- <para>Running <command>make</command> with this makefile
- will create a file <filename>skeleton.ko</filename> that can
- be loaded into the kernel by typing:</para>
-
- <screen>&prompt.root; <userinput>kldload -v ./skeleton.ko</userinput></screen>
- </sect2>
- </sect1>
-
- <sect1 xml:id="driverbasics-char">
- <title>Character Devices</title>
-
- <indexterm>
- <primary>character devices</primary>
- </indexterm>
- <para>A character device driver is one that transfers data
- directly to and from a user process. This is the most common
- type of device driver and there are plenty of simple examples in
- the source tree.</para>
-
- <para>This simple example pseudo-device remembers whatever values
- are written to it and can then echo them back when
- read.</para>
-
- <example>
- <title>Example of a Sample Echo Pseudo-Device Driver for
- &os;&nbsp;10.X - 12.X</title>
-
- <programlisting>/*
- * Simple Echo pseudo-device KLD
- *
- * Murray Stokely
- * Søren (Xride) Straarup
- * Eitan Adler
- */
-
-#include &lt;sys/types.h&gt;
-#include &lt;sys/module.h&gt;
-#include &lt;sys/systm.h&gt; /* uprintf */
-#include &lt;sys/param.h&gt; /* defines used in kernel.h */
-#include &lt;sys/kernel.h&gt; /* types used in module initialization */
-#include &lt;sys/conf.h&gt; /* cdevsw struct */
-#include &lt;sys/uio.h&gt; /* uio struct */
-#include &lt;sys/malloc.h&gt;
-
-#define BUFFERSIZE 255
-
-/* Function prototypes */
-static d_open_t echo_open;
-static d_close_t echo_close;
-static d_read_t echo_read;
-static d_write_t echo_write;
-
-/* Character device entry points */
-static struct cdevsw echo_cdevsw = {
- .d_version = D_VERSION,
- .d_open = echo_open,
- .d_close = echo_close,
- .d_read = echo_read,
- .d_write = echo_write,
- .d_name = "echo",
-};
-
-struct s_echo {
- char msg[BUFFERSIZE + 1];
- int len;
-};
-
-/* vars */
-static struct cdev *echo_dev;
-static struct s_echo *echomsg;
-
-MALLOC_DECLARE(M_ECHOBUF);
-MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
-
-/*
- * This function 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 __unused, int what, void *arg __unused)
-{
- int error = 0;
-
- switch (what) {
- case MOD_LOAD: /* kldload */
- error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
- &amp;echo_dev,
- &amp;echo_cdevsw,
- 0,
- UID_ROOT,
- GID_WHEEL,
- 0600,
- "echo");
- if (error != 0)
- break;
-
- echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |
- M_ZERO);
- printf("Echo device loaded.\n");
- break;
- case MOD_UNLOAD:
- destroy_dev(echo_dev);
- free(echomsg, M_ECHOBUF);
- printf("Echo device unloaded.\n");
- break;
- default:
- error = EOPNOTSUPP;
- break;
- }
- return (error);
-}
-
-static int
-echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,
- struct thread *td __unused)
-{
- int error = 0;
-
- uprintf("Opened device \"echo\" successfully.\n");
- return (error);
-}
-
-static int
-echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,
- struct thread *td __unused)
-{
-
- 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)
- */
-static int
-echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
-{
- size_t amt;
- int error;
-
- /*
- * How big is this read operation? Either as big as the user wants,
- * or as big as the remaining data. Note that the 'len' does not
- * include the trailing null character.
- */
- amt = MIN(uio-&gt;uio_resid, uio-&gt;uio_offset &gt;= echomsg-&gt;len + 1 ? 0 :
- echomsg-&gt;len + 1 - uio-&gt;uio_offset);
-
- if ((error = uiomove(echomsg-&gt;msg, amt, uio)) != 0)
- uprintf("uiomove failed!\n");
-
- return (error);
-}
-
-/*
- * echo_write takes in a character string and saves it
- * to buf for later accessing.
- */
-static int
-echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
-{
- size_t amt;
- int error;
-
- /*
- * We either write from the beginning or are appending -- do
- * not allow random access.
- */
- if (uio-&gt;uio_offset != 0 &amp;&amp; (uio-&gt;uio_offset != echomsg-&gt;len))
- return (EINVAL);
-
- /* This is a new message, reset length */
- if (uio-&gt;uio_offset == 0)
- echomsg-&gt;len = 0;
-
- /* Copy the string in from user memory to kernel memory */
- amt = MIN(uio-&gt;uio_resid, (BUFFERSIZE - echomsg-&gt;len));
-
- error = uiomove(echomsg-&gt;msg + uio-&gt;uio_offset, amt, uio);
-
- /* Now we need to null terminate and record the length */
- echomsg-&gt;len = uio-&gt;uio_offset;
- echomsg-&gt;msg[echomsg-&gt;len] = 0;
-
- if (error != 0)
- uprintf("Write failed: bad address!\n");
- return (error);
-}
-
-DEV_MODULE(echo, echo_loader, NULL);</programlisting>
- </example>
-
- <para>With this driver loaded try:</para>
-
- <screen>&prompt.root; <userinput>echo -n "Test Data" &gt; /dev/echo</userinput>
-&prompt.root; <userinput>cat /dev/echo</userinput>
-Opened device "echo" successfully.
-Test Data
-Closing device "echo".</screen>
-
- <para>Real hardware devices are described in the next
- chapter.</para>
- </sect1>
-
- <sect1 xml:id="driverbasics-block">
- <title>Block Devices (Are Gone)</title>
-
- <indexterm><primary>block devices</primary></indexterm>
-
- <para>Other &unix; systems may support a second type of disk
- device known as block devices. Block devices are disk devices
- for which the kernel provides caching. This caching makes
- block-devices almost unusable, or at least dangerously
- unreliable. The caching will reorder the sequence of write
- operations, depriving the application of the ability to know the
- exact disk contents at any one instant in time.</para>
-
- <para>This makes predictable and reliable crash recovery of
- on-disk data structures (filesystems, databases, etc.)
- impossible. Since writes may be delayed, there is no way
- the kernel can report to the application which particular
- write operation encountered a write error, this further
- compounds the consistency problem.</para>
-
- <para>For this reason, no serious applications rely on block
- devices, and in fact, almost all applications which access
- disks directly take great pains to specify that character
- (or <quote>raw</quote>) devices should always be used. As
- the implementation of the aliasing of each disk (partition) to
- two devices with different semantics significantly complicated
- the relevant kernel code, &os; dropped support for cached disk
- devices as part of the modernization of the disk I/O
- infrastructure.</para>
- </sect1>
-
- <sect1 xml:id="driverbasics-net">
- <title>Network Drivers</title>
-
- <indexterm>
- <primary>network devices</primary>
- </indexterm>
- <para>Drivers for network devices do not use device nodes in order
- to be accessed. Their selection is based on other decisions
- made inside the kernel and instead of calling open(), use of a
- network device is generally introduced by using the system call
- socket(2).</para>
-
- <para>For more information see ifnet(9), the source of the
- loopback device, and Bill Paul's network drivers.</para>
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/isa/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/isa/chapter.xml
deleted file mode 100644
index 04de498a3f..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/isa/chapter.xml
+++ /dev/null
@@ -1,2514 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD$
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="isa-driver">
- <info><title>ISA Device Drivers</title>
- <authorgroup>
- <author><personname><firstname>Sergey</firstname><surname>Babkin</surname></personname><contrib>Written by </contrib></author>
- </authorgroup>
- <authorgroup>
- <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname><contrib>Modifications for Handbook made by </contrib></author>
- <author><personname><firstname>Valentino</firstname><surname>Vaschetto</surname></personname></author>
- <author><personname><firstname>Wylie</firstname><surname>Stilwell</surname></personname></author>
- </authorgroup>
- </info>
-
-
-
- <sect1 xml:id="isa-driver-synopsis">
- <title>Synopsis</title>
-
- <indexterm><primary>ISA</primary></indexterm>
- <indexterm><primary>device driver</primary><secondary>ISA</secondary></indexterm>
-
- <para>This chapter introduces the issues relevant to writing a
- driver for an ISA device. The pseudo-code presented here is
- rather detailed and reminiscent of the real code but is still
- only pseudo-code. It avoids the details irrelevant to the
- subject of the discussion. The real-life examples can be found
- in the source code of real drivers. In particular the drivers
- <literal>ep</literal> and <literal>aha</literal> are good sources of information.</para>
- </sect1>
-
- <sect1 xml:id="isa-driver-basics">
- <title>Basic Information</title>
-
- <para>A typical ISA driver would need the following include
- files:</para>
-
-<programlisting>#include &lt;sys/module.h&gt;
-#include &lt;sys/bus.h&gt;
-#include &lt;machine/bus.h&gt;
-#include &lt;machine/resource.h&gt;
-#include &lt;sys/rman.h&gt;
-
-#include &lt;isa/isavar.h&gt;
-#include &lt;isa/pnpvar.h&gt;</programlisting>
-
- <para>They describe the things specific to the ISA and generic
- bus subsystem.</para>
-
- <indexterm><primary>object-oriented</primary></indexterm>
- <para>The bus subsystem is implemented in an object-oriented
- fashion, its main structures are accessed by associated method
- functions.</para>
-
- <indexterm><primary>bus methods</primary></indexterm>
- <para>The list of bus methods implemented by an ISA driver is like
- one for any other bus. For a hypothetical driver named <quote>xxx</quote>
- they would be:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>static void xxx_isa_identify (driver_t *,
- device_t);</function> Normally used for bus drivers, not
- device drivers. But for ISA devices this method may have
- special use: if the device provides some device-specific
- (non-PnP) way to auto-detect devices this routine may
- implement it.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_probe (device_t
- dev);</function> Probe for a device at a known (or PnP)
- location. This routine can also accommodate device-specific
- auto-detection of parameters for partially configured
- devices.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_attach (device_t
- dev);</function> Attach and initialize device.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_detach (device_t
- dev);</function> Detach device before unloading the driver
- module.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_shutdown (device_t
- dev);</function> Execute shutdown of the device before
- system shutdown.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_suspend (device_t
- dev);</function> Suspend the device before the system goes
- to the power-save state. May also abort transition to the
- power-save state.</para>
- </listitem>
-
- <listitem>
- <para><function>static int xxx_isa_resume (device_t
- dev);</function> Resume the device activity after return
- from power-save state.</para>
- </listitem>
-
- </itemizedlist>
-
- <para><function>xxx_isa_probe()</function> and
- <function>xxx_isa_attach()</function> are mandatory, the rest of
- the routines are optional, depending on the device's
- needs.</para>
-
- <para>The driver is linked to the system with the following set of
- descriptions.</para>
-
-<programlisting> /* table of supported bus methods */
- static device_method_t xxx_isa_methods[] = {
- /* list all the bus method functions supported by the driver */
- /* omit the unsupported methods */
- DEVMETHOD(device_identify, xxx_isa_identify),
- DEVMETHOD(device_probe, xxx_isa_probe),
- DEVMETHOD(device_attach, xxx_isa_attach),
- DEVMETHOD(device_detach, xxx_isa_detach),
- DEVMETHOD(device_shutdown, xxx_isa_shutdown),
- DEVMETHOD(device_suspend, xxx_isa_suspend),
- DEVMETHOD(device_resume, xxx_isa_resume),
-
- DEVMETHOD_END
- };
-
- static driver_t xxx_isa_driver = {
- "xxx",
- xxx_isa_methods,
- sizeof(struct xxx_softc),
- };
-
-
- static devclass_t xxx_devclass;
-
- DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,
- load_function, load_argument);</programlisting>
-
- <indexterm><primary>softc</primary></indexterm>
-
- <para>Here struct <varname remap="structname">xxx_softc</varname> is a
- device-specific structure that contains private driver data
- and descriptors for the driver's resources. The bus code
- automatically allocates one softc descriptor per device as
- needed.</para>
-
- <indexterm><primary>kernel module</primary></indexterm>
-
- <para>If the driver is implemented as a loadable module then
- <function>load_function()</function> is called to do
- driver-specific initialization or clean-up when the driver is
- loaded or unloaded and load_argument is passed as one of its
- arguments. If the driver does not support dynamic loading (in
- other words it must always be linked into the kernel) then these
- values should be set to 0 and the last definition would look
- like:</para>
-
- <programlisting> DRIVER_MODULE(xxx, isa, xxx_isa_driver,
- xxx_devclass, 0, 0);</programlisting>
-
- <indexterm><primary>PnP</primary></indexterm>
-
- <para>If the driver is for a device which supports PnP then a
- table of supported PnP IDs must be defined. The table
- consists of a list of PnP IDs supported by this driver and
- human-readable descriptions of the hardware types and models
- having these IDs. It looks like:</para>
-
-<programlisting> static struct isa_pnp_id xxx_pnp_ids[] = {
- /* a line for each supported PnP ID */
- { 0x12345678, "Our device model 1234A" },
- { 0x12345679, "Our device model 1234B" },
- { 0, NULL }, /* end of table */
- };</programlisting>
-
- <para>If the driver does not support PnP devices it still needs
- an empty PnP ID table, like:</para>
-
-<programlisting> static struct isa_pnp_id xxx_pnp_ids[] = {
- { 0, NULL }, /* end of table */
- };</programlisting>
-
- </sect1>
-
- <sect1 xml:id="isa-driver-device-t">
- <title><varname remap="structname">device_t</varname> Pointer</title>
-
- <para><varname remap="structname">device_t</varname> is the pointer type for
- the device structure. Here we consider only the methods
- interesting from the device driver writer's standpoint. The
- methods to manipulate values in the device structure
- are:</para>
-
- <itemizedlist>
-
- <listitem><para><function>device_t
- device_get_parent(dev)</function> Get the parent bus of a
- device.</para></listitem>
-
- <listitem><para><function>driver_t
- device_get_driver(dev)</function> Get pointer to its driver
- structure.</para></listitem>
-
- <listitem><para><function>char
- *device_get_name(dev)</function> Get the driver name, such
- as <literal>"xxx"</literal> for our example.</para></listitem>
-
- <listitem><para><function>int device_get_unit(dev)</function>
- Get the unit number (units are numbered from 0 for the
- devices associated with each driver).</para></listitem>
-
- <listitem><para><function>char
- *device_get_nameunit(dev)</function> Get the device name
- including the unit number, such as <quote>xxx0</quote>, <quote>xxx1</quote> and so
- on.</para></listitem>
-
- <listitem><para><function>char
- *device_get_desc(dev)</function> Get the device
- description. Normally it describes the exact model of device
- in human-readable form.</para></listitem>
-
- <listitem><para><function>device_set_desc(dev,
- desc)</function> Set the description. This makes the device
- description point to the string desc which may not be
- deallocated or changed after that.</para></listitem>
-
- <listitem><para><function>device_set_desc_copy(dev,
- desc)</function> Set the description. The description is
- copied into an internal dynamically allocated buffer, so the
- string desc may be changed afterwards without adverse
- effects.</para></listitem>
-
- <listitem><para><function>void
- *device_get_softc(dev)</function> Get pointer to the device
- descriptor (struct <varname remap="structname">xxx_softc</varname>)
- associated with this device.</para></listitem>
-
- <listitem><para><function>u_int32_t
- device_get_flags(dev)</function> Get the flags specified for
- the device in the configuration file.</para></listitem>
-
- </itemizedlist>
-
- <para>A convenience function <function>device_printf(dev, fmt,
- ...)</function> may be used to print the messages from the
- device driver. It automatically prepends the unitname and
- colon to the message.</para>
-
- <para>The device_t methods are implemented in the file
- <filename>kern/bus_subr.c</filename>.</para>
-
- </sect1>
-
- <sect1 xml:id="isa-driver-config">
- <title>Configuration File and the Order of Identifying and Probing
- During Auto-Configuration</title>
-
- <indexterm><primary>ISA</primary><secondary>probing</secondary></indexterm>
-
- <para>The ISA devices are described in the kernel configuration file
- like:</para>
-
- <programlisting>device xxx0 at isa? port 0x300 irq 10 drq 5
- iomem 0xd0000 flags 0x1 sensitive</programlisting>
-
- <indexterm><primary>IRQ</primary></indexterm>
-
- <para>The values of port, IRQ and so on are converted to the
- resource values associated with the device. They are optional,
- depending on the device's needs and abilities for
- auto-configuration. For example, some devices do not need DRQ
- at all and some allow the driver to read the IRQ setting from
- the device configuration ports. If a machine has multiple ISA
- buses the exact bus may be specified in the configuration
- line, like <literal>isa0</literal> or <literal>isa1</literal>, otherwise the device would be
- searched for on all the ISA buses.</para>
-
- <para><literal>sensitive</literal> is a resource requesting that this device must
- be probed before all non-sensitive devices. It is supported
- but does not seem to be used in any current driver.</para>
-
- <para>For legacy ISA devices in many cases the drivers are still
- able to detect the configuration parameters. But each device
- to be configured in the system must have a config line. If two
- devices of some type are installed in the system but there is
- only one configuration line for the corresponding driver, ie:
- <programlisting>device xxx0 at isa?</programlisting> then only
- one device will be configured.</para>
-
- <para>But for the devices supporting automatic identification by
- the means of Plug-n-Play or some proprietary protocol one
- configuration line is enough to configure all the devices in
- the system, like the one above or just simply:</para>
-
- <programlisting>device xxx at isa?</programlisting>
-
- <para>If a driver supports both auto-identified and legacy
- devices and both kinds are installed at once in one machine
- then it is enough to describe in the config file the legacy
- devices only. The auto-identified devices will be added
- automatically.</para>
-
- <para>When an ISA bus is auto-configured the events happen as
- follows:</para>
-
- <para>All the drivers' identify routines (including the PnP
- identify routine which identifies all the PnP devices) are
- called in random order. As they identify the devices they add
- them to the list on the ISA bus. Normally the drivers'
- identify routines associate their drivers with the new
- devices. The PnP identify routine does not know about the
- other drivers yet so it does not associate any with the new
- devices it adds.</para>
-
- <para>The PnP devices are put to sleep using the PnP protocol to
- prevent them from being probed as legacy devices.</para>
-
- <para>The probe routines of non-PnP devices marked as
- <literal>sensitive</literal> are called. If probe for a device went
- successfully, the attach routine is called for it.</para>
-
- <para>The probe and attach routines of all non-PNP devices are
- called likewise.</para>
-
- <para>The PnP devices are brought back from the sleep state and
- assigned the resources they request: I/O and memory address
- ranges, IRQs and DRQs, all of them not conflicting with the
- attached legacy devices.</para>
-
- <para>Then for each PnP device the probe routines of all the
- present ISA drivers are called. The first one that claims the
- device gets attached. It is possible that multiple drivers
- would claim the device with different priority; in this case, the
- highest-priority driver wins. The probe routines must call
- <function>ISA_PNP_PROBE()</function> to compare the actual PnP
- ID with the list of the IDs supported by the driver and if the
- ID is not in the table return failure. That means that
- absolutely every driver, even the ones not supporting any PnP
- devices must call <function>ISA_PNP_PROBE()</function>, at
- least with an empty PnP ID table to return failure on unknown
- PnP devices.</para>
-
- <para>The probe routine returns a positive value (the error
- code) on error, zero or negative value on success.</para>
-
- <para>The negative return values are used when a PnP device
- supports multiple interfaces. For example, an older
- compatibility interface and a newer advanced interface which
- are supported by different drivers. Then both drivers would
- detect the device. The driver which returns a higher value in
- the probe routine takes precedence (in other words, the driver
- returning 0 has highest precedence, returning -1 is next,
- returning -2 is after it and so on). In result the devices
- which support only the old interface will be handled by the
- old driver (which should return -1 from the probe routine)
- while the devices supporting the new interface as well will be
- handled by the new driver (which should return 0 from the
- probe routine). If multiple drivers return the same value then
- the one called first wins. So if a driver returns value 0 it
- may be sure that it won the priority arbitration.</para>
-
- <para>The device-specific identify routines can also assign not
- a driver but a class of drivers to the device. Then all the
- drivers in the class are probed for this device, like the case
- with PnP. This feature is not implemented in any existing
- driver and is not considered further in this document.</para>
-
- <para>As the PnP devices are disabled when probing the
- legacy devices they will not be attached twice (once as legacy
- and once as PnP). But in case of device-dependent identify
- routines it is the responsibility of the driver to make sure
- that the same device will not be attached by the driver twice:
- once as legacy user-configured and once as
- auto-identified.</para>
-
- <para>Another practical consequence for the auto-identified
- devices (both PnP and device-specific) is that the flags can
- not be passed to them from the kernel configuration file. So
- they must either not use the flags at all or use the flags
- from the device unit 0 for all the auto-identified devices or
- use the sysctl interface instead of flags.</para>
-
- <para>Other unusual configurations may be accommodated by
- accessing the configuration resources directly with functions
- of families <function>resource_query_*()</function> and
- <function>resource_*_value()</function>. Their implementations
- are located in <filename>kern/subr_bus.c</filename>. The old IDE disk driver
- <filename>i386/isa/wd.c</filename> contains examples of such use. But the standard
- means of configuration must always be preferred. Leave parsing
- the configuration resources to the bus configuration
- code.</para>
-
- </sect1>
-
- <sect1 xml:id="isa-driver-resources">
- <title>Resources</title>
-
- <indexterm><primary>resources</primary></indexterm>
- <indexterm><primary>device driver</primary><secondary>resources</secondary></indexterm>
-
- <para>The information that a user enters into the kernel
- configuration file is processed and passed to the kernel as
- configuration resources. This information is parsed by the bus
- configuration code and transformed into a value of structure
- device_t and the bus resources associated with it. The drivers
- may access the configuration resources directly using
- functions <function>resource_*</function> for more complex cases of
- configuration. However, generally this is neither needed nor recommended,
- so this issue is not discussed further here.</para>
-
- <para>The bus resources are associated with each device. They
- are identified by type and number within the type. For the ISA
- bus the following types are defined:</para>
-
- <indexterm><primary>DMA channel</primary></indexterm>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>SYS_RES_IRQ</emphasis> - interrupt
- number</para>
- </listitem>
-
- <listitem>
- <para><emphasis>SYS_RES_DRQ</emphasis> - ISA DMA channel
- number</para>
- </listitem>
-
- <listitem>
- <para><emphasis>SYS_RES_MEMORY</emphasis> - range of
- device memory mapped into the system memory space
- </para>
- </listitem>
-
- <listitem>
- <para><emphasis>SYS_RES_IOPORT</emphasis> - range of
- device I/O registers</para>
- </listitem>
- </itemizedlist>
-
- <para>The enumeration within types starts from 0, so if a device
- has two memory regions it would have resources of type
- <literal>SYS_RES_MEMORY</literal> numbered 0 and 1. The resource type has
- nothing to do with the C language type, all the resource
- values have the C language type <literal>unsigned long</literal> and must be
- cast as necessary. The resource numbers do not have to be
- contiguous, although for ISA they normally would be. The
- permitted resource numbers for ISA devices are:</para>
-
- <programlisting> IRQ: 0-1
- DRQ: 0-1
- MEMORY: 0-3
- IOPORT: 0-7</programlisting>
-
- <para>All the resources are represented as ranges, with a start
- value and count. For IRQ and DRQ resources the count would
- normally be equal to 1. The values for memory refer to the
- physical addresses.</para>
-
- <para>Three types of activities can be performed on
- resources:</para>
-
- <itemizedlist>
- <listitem><para>set/get</para></listitem>
- <listitem><para>allocate/release</para></listitem>
- <listitem><para>activate/deactivate</para></listitem>
- </itemizedlist>
-
- <para>Setting sets the range used by the resource. Allocation
- reserves the requested range that no other driver would be
- able to reserve it (and checking that no other driver reserved
- this range already). Activation makes the resource accessible
- to the driver by doing whatever is necessary for that (for
- example, for memory it would be mapping into the kernel
- virtual address space).</para>
-
- <para>The functions to manipulate resources are:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>int bus_set_resource(device_t dev, int type,
- int rid, u_long start, u_long count)</function></para>
-
- <para>Set a range for a resource. Returns 0 if successful,
- error code otherwise. Normally, this function will
- return an error only if one of <literal>type</literal>,
- <literal>rid</literal>, <literal>start</literal> or
- <literal>count</literal> has a value that falls out of the
- permitted range.</para>
-
- <itemizedlist>
- <listitem>
- <para> dev - driver's device</para>
- </listitem>
- <listitem>
- <para> type - type of resource, SYS_RES_* </para>
- </listitem>
- <listitem>
- <para> rid - resource number (ID) within type </para>
- </listitem>
- <listitem>
- <para> start, count - resource range </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem>
- <para><function>int bus_get_resource(device_t dev, int type,
- int rid, u_long *startp, u_long *countp)</function></para>
-
- <para>Get the range of resource. Returns 0 if successful,
- error code if the resource is not defined yet.</para>
- </listitem>
-
- <listitem>
- <para><function>u_long bus_get_resource_start(device_t dev,
- int type, int rid) u_long bus_get_resource_count (device_t
- dev, int type, int rid)</function></para>
-
- <para>Convenience functions to get only the start or
- count. Return 0 in case of error, so if the resource start
- has 0 among the legitimate values it would be impossible
- to tell if the value is 0 or an error occurred. Luckily,
- no ISA resources for add-on drivers may have a start value
- equal to 0.</para>
- </listitem>
-
- <listitem>
- <para><function>void bus_delete_resource(device_t dev, int
- type, int rid)</function></para>
- <para> Delete a resource, make it undefined.</para>
- </listitem>
-
- <listitem>
- <para><function>struct resource *
- bus_alloc_resource(device_t dev, int type, int *rid,
- u_long start, u_long end, u_long count, u_int
- flags)</function></para>
-
- <para>Allocate a resource as a range of count values not
- allocated by anyone else, somewhere between start and
- end. Alas, alignment is not supported. If the resource
- was not set yet it is automatically created. The special
- values of start 0 and end ~0 (all ones) means that the
- fixed values previously set by
- <function>bus_set_resource()</function> must be used
- instead: start and count as themselves and
- end=(start+count), in this case if the resource was not
- defined before then an error is returned. Although rid is
- passed by reference it is not set anywhere by the resource
- allocation code of the ISA bus. (The other buses may use a
- different approach and modify it).</para>
- </listitem>
- </itemizedlist>
-
- <para>Flags are a bitmap, the flags interesting for the caller
- are:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>RF_ACTIVE</emphasis> - causes the resource
- to be automatically activated after allocation.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>RF_SHAREABLE</emphasis> - resource may be
- shared at the same time by multiple drivers.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>RF_TIMESHARE</emphasis> - resource may be
- time-shared by multiple drivers, i.e., allocated at the
- same time by many but activated only by one at any given
- moment of time.</para>
- </listitem>
-<!-- XXXDONT KNOW IT THESE SHOULD BE TWO SEPARATE LISTS OR NOT -->
- <listitem>
- <para>Returns 0 on error. The allocated values may be
- obtained from the returned handle using methods
- <function>rhand_*()</function>.</para>
- </listitem>
- <listitem>
- <para><function>int bus_release_resource(device_t dev, int
- type, int rid, struct resource *r)</function></para>
- </listitem>
-
- <listitem>
- <para>Release the resource, r is the handle returned by
- <function>bus_alloc_resource()</function>. Returns 0 on
- success, error code otherwise.</para>
- </listitem>
-
- <listitem>
- <para><function>int bus_activate_resource(device_t dev, int
- type, int rid, struct resource *r)</function>
- <function>int bus_deactivate_resource(device_t dev, int
- type, int rid, struct resource *r)</function></para>
- </listitem>
-
- <listitem>
- <para>Activate or deactivate resource. Return 0 on success,
- error code otherwise. If the resource is time-shared and
- currently activated by another driver then <literal>EBUSY</literal> is
- returned.</para>
- </listitem>
-
- <listitem>
- <para><function>int bus_setup_intr(device_t dev, struct
- resource *r, int flags, driver_intr_t *handler, void *arg,
- void **cookiep)</function> <function>int
- bus_teardown_intr(device_t dev, struct resource *r, void
- *cookie)</function></para>
- </listitem>
-
- <listitem>
- <para>Associate or de-associate the interrupt handler with a
- device. Return 0 on success, error code otherwise.</para>
- </listitem>
-
- <listitem>
- <para>r - the activated resource handler describing the
- IRQ</para>
- <para>flags - the interrupt priority level, one of:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>INTR_TYPE_TTY</function> - terminals and
- other likewise character-type devices. To mask them
- use <function>spltty()</function>.</para>
- </listitem>
- <listitem>
- <para><function>(INTR_TYPE_TTY |
- INTR_TYPE_FAST)</function> - terminal type devices
- with small input buffer, critical to the data loss on
- input (such as the old-fashioned serial ports). To
- mask them use <function>spltty()</function>.</para>
- </listitem>
- <listitem>
- <para><function>INTR_TYPE_BIO</function> - block-type
- devices, except those on the CAM controllers. To mask
- them use <function>splbio()</function>.</para>
- </listitem>
- <listitem>
- <para><function>INTR_TYPE_CAM</function> - CAM (Common
- Access Method) bus controllers. To mask them use
- <function>splcam()</function>.</para>
- </listitem>
- <listitem>
- <para><function>INTR_TYPE_NET</function> - network
- interface controllers. To mask them use
- <function>splimp()</function>.</para>
- </listitem>
- <listitem>
- <para><function>INTR_TYPE_MISC</function> -
- miscellaneous devices. There is no other way to mask
- them than by <function>splhigh()</function> which
- masks all interrupts.</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-
- <para>When an interrupt handler executes all the other
- interrupts matching its priority level will be masked. The
- only exception is the MISC level for which no other interrupts
- are masked and which is not masked by any other
- interrupt.</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>handler</emphasis> - pointer to the handler
- function, the type driver_intr_t is defined as <function>void
- driver_intr_t(void *)</function></para>
- </listitem>
- <listitem>
- <para><emphasis>arg</emphasis> - the argument passed to the
- handler to identify this particular device. It is cast
- from void* to any real type by the handler. The old
- convention for the ISA interrupt handlers was to use the
- unit number as argument, the new (recommended) convention
- is using a pointer to the device softc structure.</para>
- </listitem>
- <listitem>
- <para><emphasis>cookie[p]</emphasis> - the value received
- from <function>setup()</function> is used to identify the
- handler when passed to
- <function>teardown()</function></para>
- </listitem>
- </itemizedlist>
-
- <para>A number of methods are defined to operate on the resource
- handlers (struct resource *). Those of interest to the device
- driver writers are:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>u_long rman_get_start(r) u_long
- rman_get_end(r)</function> Get the start and end of
- allocated resource range.</para>
- </listitem>
- <listitem>
- <para><function>void *rman_get_virtual(r)</function> Get
- the virtual address of activated memory resource.</para>
- </listitem>
- </itemizedlist>
-
- </sect1>
-
- <sect1 xml:id="isa-driver-busmem">
- <title>Bus Memory Mapping</title>
-
- <para>In many cases data is exchanged between the driver and the
- device through the memory. Two variants are possible:</para>
-
- <para>(a) memory is located on the device card</para>
- <para>(b) memory is the main memory of the computer</para>
-
- <para>In case (a) the driver always copies the data back and
- forth between the on-card memory and the main memory as
- necessary. To map the on-card memory into the kernel virtual
- address space the physical address and length of the on-card
- memory must be defined as a <literal>SYS_RES_MEMORY</literal> resource. That
- resource can then be allocated and activated, and its virtual
- address obtained using
- <function>rman_get_virtual()</function>. The older drivers
- used the function <function>pmap_mapdev()</function> for this
- purpose, which should not be used directly any more. Now it is
- one of the internal steps of resource activation.</para>
-
- <para>Most of the ISA cards will have their memory configured
- for physical location somewhere in range 640KB-1MB. Some of
- the ISA cards require larger memory ranges which should be
- placed somewhere under 16MB (because of the 24-bit address
- limitation on the ISA bus). In that case if the machine has
- more memory than the start address of the device memory (in
- other words, they overlap) a memory hole must be configured at
- the address range used by devices. Many BIOSes allow
- configuration of a memory hole of 1MB starting at 14MB or
- 15MB. FreeBSD can handle the memory holes properly if the BIOS
- reports them properly (this feature may be broken on old BIOSes).</para>
-
- <para>In case (b) just the address of the data is sent to
- the device, and the device uses DMA to actually access the
- data in the main memory. Two limitations are present: First,
- ISA cards can only access memory below 16MB. Second, the
- contiguous pages in virtual address space may not be
- contiguous in physical address space, so the device may have
- to do scatter/gather operations. The bus subsystem provides
- ready solutions for some of these problems, the rest has to be
- done by the drivers themselves.</para>
-
- <para>Two structures are used for DMA memory allocation,
- <varname>bus_dma_tag_t</varname> and <varname>bus_dmamap_t</varname>. Tag describes the properties
- required for the DMA memory. Map represents a memory block
- allocated according to these properties. Multiple maps may be
- associated with the same tag.</para>
-
- <para>Tags are organized into a tree-like hierarchy with
- inheritance of the properties. A child tag inherits all the
- requirements of its parent tag, and may make them more strict
- but never more loose.</para>
-
- <para>Normally one top-level tag (with no parent) is created for
- each device unit. If multiple memory areas with different
- requirements are needed for each device then a tag for each of
- them may be created as a child of the parent tag.</para>
-
- <para>The tags can be used to create a map in two ways.</para>
-
- <para>First, a chunk of contiguous memory conformant with the
- tag requirements may be allocated (and later may be
- freed). This is normally used to allocate relatively
- long-living areas of memory for communication with the
- device. Loading of such memory into a map is trivial: it is
- always considered as one chunk in the appropriate physical
- memory range.</para>
-
- <para>Second, an arbitrary area of virtual memory may be loaded
- into a map. Each page of this memory will be checked for
- conformance to the map requirement. If it conforms then it is
- left at its original location. If it is not then a fresh
- conformant <quote>bounce page</quote> is allocated and used as intermediate
- storage. When writing the data from the non-conformant
- original pages they will be copied to their bounce pages first
- and then transferred from the bounce pages to the device. When
- reading the data would go from the device to the bounce pages
- and then copied to their non-conformant original pages. The
- process of copying between the original and bounce pages is
- called synchronization. This is normally used on a per-transfer
- basis: buffer for each transfer would be loaded, transfer done
- and buffer unloaded.</para>
-
- <para>The functions working on the DMA memory are:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>int bus_dma_tag_create(bus_dma_tag_t parent,
- bus_size_t alignment, bus_size_t boundary, bus_addr_t
- lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void
- *filterarg, bus_size_t maxsize, int nsegments, bus_size_t
- maxsegsz, int flags, bus_dma_tag_t *dmat)</function></para>
-
- <para>Create a new tag. Returns 0 on success, the error code
- otherwise.</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>parent</emphasis> - parent tag, or NULL to
- create a top-level tag.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>alignment</emphasis> -
- required physical alignment of the memory area to be
- allocated for this tag. Use value 1 for <quote>no specific
- alignment</quote>. Applies only to the future
- <function>bus_dmamem_alloc()</function> but not
- <function>bus_dmamap_create()</function> calls.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>boundary</emphasis> - physical address
- boundary that must not be crossed when allocating the
- memory. Use value 0 for <quote>no boundary</quote>. Applies only to
- the future <function>bus_dmamem_alloc()</function> but
- not <function>bus_dmamap_create()</function> calls.
- Must be power of 2. If the memory is planned to be used
- in non-cascaded DMA mode (i.e., the DMA addresses will be
- supplied not by the device itself but by the ISA DMA
- controller) then the boundary must be no larger than
- 64KB (64*1024) due to the limitations of the DMA
- hardware.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>lowaddr, highaddr</emphasis> - the names
- are slightly misleading; these values are used to limit
- the permitted range of physical addresses used to
- allocate the memory. The exact meaning varies depending
- on the planned future use:</para>
-
- <itemizedlist>
- <listitem>
- <para>For <function>bus_dmamem_alloc()</function> all
- the addresses from 0 to lowaddr-1 are considered
- permitted, the higher ones are forbidden.</para>
- </listitem>
-
- <listitem>
- <para>For <function>bus_dmamap_create()</function> all
- the addresses outside the inclusive range [lowaddr;
- highaddr] are considered accessible. The addresses
- of pages inside the range are passed to the filter
- function which decides if they are accessible. If no
- filter function is supplied then all the range is
- considered unaccessible.</para>
- </listitem>
-
- <listitem>
- <para>For the ISA devices the normal values (with no
- filter function) are:</para>
- <para>lowaddr = BUS_SPACE_MAXADDR_24BIT</para>
- <para>highaddr = BUS_SPACE_MAXADDR</para>
- </listitem>
- </itemizedlist>
-
- </listitem>
-
- <listitem>
- <para><emphasis>filter, filterarg</emphasis> - the filter
- function and its argument. If NULL is passed for filter
- then the whole range [lowaddr, highaddr] is considered
- unaccessible when doing
- <function>bus_dmamap_create()</function>. Otherwise the
- physical address of each attempted page in range
- [lowaddr; highaddr] is passed to the filter function
- which decides if it is accessible. The prototype of the
- filter function is: <function>int filterfunc(void *arg,
- bus_addr_t paddr)</function>. It must return 0 if the
- page is accessible, non-zero otherwise.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>maxsize</emphasis> - the maximal size of
- memory (in bytes) that may be allocated through this
- tag. In case it is difficult to estimate or could be
- arbitrarily big, the value for ISA devices would be
- <literal>BUS_SPACE_MAXSIZE_24BIT</literal>.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>nsegments</emphasis> - maximal number of
- scatter-gather segments supported by the device. If
- unrestricted then the value <literal>BUS_SPACE_UNRESTRICTED</literal>
- should be used. This value is recommended for the parent
- tags, the actual restrictions would then be specified
- for the descendant tags. Tags with nsegments equal to
- <literal>BUS_SPACE_UNRESTRICTED</literal> may not be used to actually load
- maps, they may be used only as parent tags. The
- practical limit for nsegments seems to be about 250-300,
- higher values will cause kernel stack overflow (the hardware
- can not normally support that many
- scatter-gather buffers anyway).</para>
- </listitem>
-
- <listitem>
- <para><emphasis>maxsegsz</emphasis> - maximal size of a
- scatter-gather segment supported by the device. The
- maximal value for ISA device would be
- <literal>BUS_SPACE_MAXSIZE_24BIT</literal>.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>flags</emphasis> - a bitmap of flags. The
- only interesting flags are:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>BUS_DMA_ALLOCNOW</emphasis> - requests
- to allocate all the potentially needed bounce pages
- when creating the tag.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>BUS_DMA_ISA</emphasis> - mysterious
- flag used only on Alpha machines. It is not defined
- for the i386 machines. Probably it should be used
- by all the ISA drivers for Alpha machines but it
- looks like there are no such drivers yet.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem>
- <para><emphasis>dmat</emphasis> - pointer to the storage
- for the new tag to be returned.</para>
- </listitem>
-
- </itemizedlist>
-
- </listitem>
-
- <listitem> <!-- Second entry in list alpha -->
- <para><function>int bus_dma_tag_destroy(bus_dma_tag_t
- dmat)</function></para>
-
- <para>Destroy a tag. Returns 0 on success, the error code
- otherwise.</para>
-
- <para>dmat - the tag to be destroyed.</para>
-
- </listitem>
-
- <listitem> <!-- Third entry in list alpha -->
- <para><function>int bus_dmamem_alloc(bus_dma_tag_t dmat,
- void** vaddr, int flags, bus_dmamap_t
- *mapp)</function></para>
-
- <para>Allocate an area of contiguous memory described by the
- tag. The size of memory to be allocated is tag's maxsize.
- Returns 0 on success, the error code otherwise. The result
- still has to be loaded by
- <function>bus_dmamap_load()</function> before being used to get
- the physical address of the memory.</para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>dmat</emphasis> - the tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>vaddr</emphasis> - pointer to the storage
- for the kernel virtual address of the allocated area
- to be returned.
- </para>
- </listitem>
- <listitem>
- <para>
- flags - a bitmap of flags. The only interesting flag is:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>BUS_DMA_NOWAIT</emphasis> - if the
- memory is not immediately available return the
- error. If this flag is not set then the routine
- is allowed to sleep until the memory
- becomes available.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>
- <emphasis>mapp</emphasis> - pointer to the storage
- for the new map to be returned.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem> <!-- Fourth entry in list alpha -->
- <para>
- <function>void bus_dmamem_free(bus_dma_tag_t dmat, void
- *vaddr, bus_dmamap_t map)</function>
- </para>
- <para>
- Free the memory allocated by
- <function>bus_dmamem_alloc()</function>. At present,
- freeing of the memory allocated with ISA restrictions is
- not implemented. Due to this the recommended model
- of use is to keep and re-use the allocated areas for as
- long as possible. Do not lightly free some area and then
- shortly allocate it again. That does not mean that
- <function>bus_dmamem_free()</function> should not be
- used at all: hopefully it will be properly implemented
- soon.
- </para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>dmat</emphasis> - the tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>vaddr</emphasis> - the kernel virtual
- address of the memory
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>map</emphasis> - the map of the memory (as
- returned from
- <function>bus_dmamem_alloc()</function>)
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem> <!-- The fifth entry in list alpha -->
- <para>
- <function>int bus_dmamap_create(bus_dma_tag_t dmat, int
- flags, bus_dmamap_t *mapp)</function>
- </para>
- <para>
- Create a map for the tag, to be used in
- <function>bus_dmamap_load()</function> later. Returns 0
- on success, the error code otherwise.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>dmat</emphasis> - the tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>flags</emphasis> - theoretically, a bit map
- of flags. But no flags are defined yet, so at present
- it will be always 0.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>mapp</emphasis> - pointer to the storage
- for the new map to be returned
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem> <!-- Sixth entry in the alpha list -->
- <para>
- <function>int bus_dmamap_destroy(bus_dma_tag_t dmat,
- bus_dmamap_t map)</function>
- </para>
- <para>
- Destroy a map. Returns 0 on success, the error code otherwise.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- dmat - the tag to which the map is associated
- </para>
- </listitem>
- <listitem>
- <para>
- map - the map to be destroyed
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem> <!-- Seventh entry in list alpha -->
- <para>
- <function>int bus_dmamap_load(bus_dma_tag_t dmat,
- bus_dmamap_t map, void *buf, bus_size_t buflen,
- bus_dmamap_callback_t *callback, void *callback_arg, int
- flags)</function>
- </para>
- <para>
- Load a buffer into the map (the map must be previously
- created by <function>bus_dmamap_create()</function> or
- <function>bus_dmamem_alloc()</function>). All the pages
- of the buffer are checked for conformance to the tag
- requirements and for those not conformant the bounce
- pages are allocated. An array of physical segment
- descriptors is built and passed to the callback
- routine. This callback routine is then expected to
- handle it in some way. The number of bounce buffers in
- the system is limited, so if the bounce buffers are
- needed but not immediately available the request will be
- queued and the callback will be called when the bounce
- buffers will become available. Returns 0 if the callback
- was executed immediately or <errorname>EINPROGRESS</errorname> if the request
- was queued for future execution. In the latter case the
- synchronization with queued callback routine is the
- responsibility of the driver.
- </para>
- <!--<blockquote>-->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>dmat</emphasis> - the tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>map</emphasis> - the map
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>buf</emphasis> - kernel virtual address of
- the buffer
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>buflen</emphasis> - length of the buffer
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>callback</emphasis>,<function>
- callback_arg</function> - the callback function and
- its argument
- </para>
- </listitem>
- </itemizedlist>
- <!--</blockquote>-->
- <para>
- The prototype of callback function is:
- </para>
- <para>
- <function>void callback(void *arg, bus_dma_segment_t
- *seg, int nseg, int error)</function>
- </para>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>arg</emphasis> - the same as callback_arg
- passed to <function>bus_dmamap_load()</function>
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>seg</emphasis> - array of the segment
- descriptors
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>nseg</emphasis> - number of descriptors in
- array
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>error</emphasis> - indication of the
- segment number overflow: if it is set to <errorname>EFBIG</errorname> then
- the buffer did not fit into the maximal number of
- segments permitted by the tag. In this case only the
- permitted number of descriptors will be in the
- array. Handling of this situation is up to the
- driver: depending on the desired semantics it can
- either consider this an error or split the buffer in
- two and handle the second part separately
- </para>
- </listitem>
- </itemizedlist>
- <!-- </blockquote> -->
- <para>
- Each entry in the segments array contains the fields:
- </para>
-
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>ds_addr</emphasis> - physical bus address
- of the segment
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>ds_len</emphasis> - length of the segment
- </para>
- </listitem>
- </itemizedlist>
- <!-- </blockquote>-->
- </listitem>
-
- <listitem> <!-- Eighth entry in alpha list -->
- <para>
- <function>void bus_dmamap_unload(bus_dma_tag_t dmat,
- bus_dmamap_t map)</function>
- </para>
- <para>unload the map.
- </para>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>dmat</emphasis> - tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>map</emphasis> - loaded map
- </para>
- </listitem>
- </itemizedlist>
- <!-- </blockquote> -->
- </listitem>
-
- <listitem> <!-- Ninth entry list alpha -->
- <para>
- <function>void bus_dmamap_sync (bus_dma_tag_t dmat,
- bus_dmamap_t map, bus_dmasync_op_t op)</function>
- </para>
- <para>
- Synchronise a loaded buffer with its bounce pages before
- and after physical transfer to or from device. This is
- the function that does all the necessary copying of data
- between the original buffer and its mapped version. The
- buffers must be synchronized both before and after doing
- the transfer.
- </para>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>dmat</emphasis> - tag
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>map</emphasis> - loaded map
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>op</emphasis> - type of synchronization
- operation to perform:
- </para>
- </listitem>
- </itemizedlist>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <function>BUS_DMASYNC_PREREAD</function> - before
- reading from device into buffer
- </para>
- </listitem>
- <listitem>
- <para>
- <function>BUS_DMASYNC_POSTREAD</function> - after
- reading from device into buffer
- </para>
- </listitem>
- <listitem>
- <para>
- <function>BUS_DMASYNC_PREWRITE</function> - before
- writing the buffer to device
- </para>
- </listitem>
- <listitem>
- <para>
- <function>BUS_DMASYNC_POSTWRITE</function> - after
- writing the buffer to device
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist> <!-- End of list alpha -->
-<!-- </blockquote>
-</blockquote> -->
-
- <para>
- As of now PREREAD and POSTWRITE are null operations but that
- may change in the future, so they must not be ignored in the
- driver. Synchronization is not needed for the memory
- obtained from <function>bus_dmamem_alloc()</function>.
- </para>
- <para>
- Before calling the callback function from
- <function>bus_dmamap_load()</function> the segment array is
- stored in the stack. And it gets pre-allocated for the
- maximal number of segments allowed by the tag. As a result of
- this the practical limit for the number of segments on i386
- architecture is about 250-300 (the kernel stack is 4KB minus
- the size of the user structure, size of a segment array
- entry is 8 bytes, and some space must be left). Since the
- array is allocated based on the maximal number this value
- must not be set higher than really needed. Fortunately, for
- most of hardware the maximal supported number of segments is
- much lower. But if the driver wants to handle buffers with a
- very large number of scatter-gather segments it should do
- that in portions: load part of the buffer, transfer it to
- the device, load next part of the buffer, and so on.
- </para>
- <para>
- Another practical consequence is that the number of segments
- may limit the size of the buffer. If all the pages in the
- buffer happen to be physically non-contiguous then the
- maximal supported buffer size for that fragmented case would
- be (nsegments * page_size). For example, if a maximal number
- of 10 segments is supported then on i386 maximal guaranteed
- supported buffer size would be 40K. If a higher size is
- desired then special tricks should be used in the driver.
- </para>
- <para>
- If the hardware does not support scatter-gather at all or
- the driver wants to support some buffer size even if it is
- heavily fragmented then the solution is to allocate a
- contiguous buffer in the driver and use it as intermediate
- storage if the original buffer does not fit.
- </para>
- <para>
- Below are the typical call sequences when using a map depend
- on the use of the map. The characters -&gt; are used to show
- the flow of time.
- </para>
- <para>
- For a buffer which stays practically fixed during all the
- time between attachment and detachment of a device:</para>
- <para>
- bus_dmamem_alloc -&gt; bus_dmamap_load -&gt; ...use buffer... -&gt;
- -&gt; bus_dmamap_unload -&gt; bus_dmamem_free
- </para>
-
- <para>For a buffer that changes frequently and is passed from
- outside the driver:
-
- <!-- XXX is this correct? -->
- <programlisting> bus_dmamap_create -&gt;
- -&gt; bus_dmamap_load -&gt; bus_dmamap_sync(PRE...) -&gt; do transfer -&gt;
- -&gt; bus_dmamap_sync(POST...) -&gt; bus_dmamap_unload -&gt;
- ...
- -&gt; bus_dmamap_load -&gt; bus_dmamap_sync(PRE...) -&gt; do transfer -&gt;
- -&gt; bus_dmamap_sync(POST...) -&gt; bus_dmamap_unload -&gt;
- -&gt; bus_dmamap_destroy </programlisting>
-
- </para>
- <para>
- When loading a map created by
- <function>bus_dmamem_alloc()</function> the passed address
- and size of the buffer must be the same as used in
- <function>bus_dmamem_alloc()</function>. In this case it is
- guaranteed that the whole buffer will be mapped as one
- segment (so the callback may be based on this assumption)
- and the request will be executed immediately (EINPROGRESS
- will never be returned). All the callback needs to do in
- this case is to save the physical address.
- </para>
- <para>
- A typical example would be:
- </para>
-
- <programlisting> static void
- alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
- {
- *(bus_addr_t *)arg = seg[0].ds_addr;
- }
-
- ...
- int error;
- struct somedata {
- ....
- };
- struct somedata *vsomedata; /* virtual address */
- bus_addr_t psomedata; /* physical bus-relative address */
- bus_dma_tag_t tag_somedata;
- bus_dmamap_t map_somedata;
- ...
-
- error=bus_dma_tag_create(parent_tag, alignment,
- boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,
- /*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,
- /*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,
- &#38;tag_somedata);
- if(error)
- return error;
-
- error = bus_dmamem_alloc(tag_somedata, &#38;vsomedata, /* flags*/ 0,
- &#38;map_somedata);
- if(error)
- return error;
-
- bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,
- sizeof (struct somedata), alloc_callback,
- (void *) &#38;psomedata, /*flags*/0); </programlisting>
-
- <para>
- Looks a bit long and complicated but that is the way to do
- it. The practical consequence is: if multiple memory areas
- are allocated always together it would be a really good idea
- to combine them all into one structure and allocate as one
- (if the alignment and boundary limitations permit).
- </para>
- <para>
- When loading an arbitrary buffer into the map created by
- <function>bus_dmamap_create()</function> special measures
- must be taken to synchronize with the callback in case it
- would be delayed. The code would look like:
- </para>
-
- <programlisting> {
- int s;
- int error;
-
- s = splsoftvm();
- error = bus_dmamap_load(
- dmat,
- dmamap,
- buffer_ptr,
- buffer_len,
- callback,
- /*callback_arg*/ buffer_descriptor,
- /*flags*/0);
- if (error == EINPROGRESS) {
- /*
- * Do whatever is needed to ensure synchronization
- * with callback. Callback is guaranteed not to be started
- * until we do splx() or tsleep().
- */
- }
- splx(s);
- } </programlisting>
-
- <para>
- Two possible approaches for the processing of requests are:
- </para>
- <para>
- 1. If requests are completed by marking them explicitly as
- done (such as the CAM requests) then it would be simpler to
- put all the further processing into the callback driver
- which would mark the request when it is done. Then not much
- extra synchronization is needed. For the flow control
- reasons it may be a good idea to freeze the request queue
- until this request gets completed.
- </para>
- <para>
- 2. If requests are completed when the function returns (such
- as classic read or write requests on character devices) then
- a synchronization flag should be set in the buffer
- descriptor and <function>tsleep()</function> called. Later
- when the callback gets called it will do its processing and
- check this synchronization flag. If it is set then the
- callback should issue a wakeup. In this approach the
- callback function could either do all the needed processing
- (just like the previous case) or simply save the segments
- array in the buffer descriptor. Then after callback
- completes the calling function could use this saved segments
- array and do all the processing.
-
- </para>
- </sect1>
-<!--_________________________________________________________________________-->
-<!--~~~~~~~~~~~~~~~~~~~~END OF SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-
- <sect1 xml:id="isa-driver-dma">
- <title>DMA</title>
- <!-- Section Marked up by Wylie -->
-
- <indexterm><primary>Direct Memory Access (DMA)</primary></indexterm>
-
- <para>
- The Direct Memory Access (DMA) is implemented in the ISA bus
- through the DMA controller (actually, two of them but that is
- an irrelevant detail). To make the early ISA devices simple
- and cheap the logic of the bus control and address
- generation was concentrated in the DMA controller.
- Fortunately, FreeBSD provides a set of functions that mostly
- hide the annoying details of the DMA controller from the
- device drivers.
- </para>
-
- <para>
- The simplest case is for the fairly intelligent
- devices. Like the bus master devices on PCI they can
- generate the bus cycles and memory addresses all by
- themselves. The only thing they really need from the DMA
- controller is bus arbitration. So for this purpose they
- pretend to be cascaded slave DMA controllers. And the only
- thing needed from the system DMA controller is to enable the
- cascaded mode on a DMA channel by calling the following
- function when attaching the driver:
- </para>
-
- <para>
- <function>void isa_dmacascade(int channel_number)</function>
- </para>
-
- <para>
- All the further activity is done by programming the
- device. When detaching the driver no DMA-related functions
- need to be called.
- </para>
-
- <para>
- For the simpler devices things get more complicated. The
- functions used are:
- </para>
-
- <itemizedlist>
-
- <listitem>
- <para>
- <function>int isa_dma_acquire(int chanel_number)</function>
- </para>
- <para>
- Reserve a DMA channel. Returns 0 on success or EBUSY
- if the channel was already reserved by this or a
- different driver. Most of the ISA devices are not able
- to share DMA channels anyway, so normally this
- function is called when attaching a device. This
- reservation was made redundant by the modern interface
- of bus resources but still must be used in addition to
- the latter. If not used then later, other DMA routines
- will panic.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <function>int isa_dma_release(int chanel_number)</function>
- </para>
- <para>
- Release a previously reserved DMA channel. No
- transfers must be in progress when the channel is
- released (in addition the device must not try to
- initiate transfer after the channel is released).
- </para>
- </listitem>
-
- <listitem>
- <para>
- <function>void isa_dmainit(int chan, u_int
- bouncebufsize)</function>
- </para>
- <para>
- Allocate a bounce buffer for use with the specified
- channel. The requested size of the buffer can not exceed
- 64KB. This bounce buffer will be automatically used
- later if a transfer buffer happens to be not
- physically contiguous or outside of the memory
- accessible by the ISA bus or crossing the 64KB
- boundary. If the transfers will be always done from
- buffers which conform to these conditions (such as
- those allocated by
- <function>bus_dmamem_alloc()</function> with proper
- limitations) then <function>isa_dmainit()</function>
- does not have to be called. But it is quite convenient
- to transfer arbitrary data using the DMA controller.
- The bounce buffer will automatically care of the
- scatter-gather issues.
- </para>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>chan</emphasis> - channel number
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bouncebufsize</emphasis> - size of the
- bounce buffer in bytes
- </para>
- </listitem>
- </itemizedlist>
-<!-- </blockquote> -->
-<!--</para> -->
- </listitem>
-
- <listitem>
- <para>
- <function>void isa_dmastart(int flags, caddr_t addr, u_int
- nbytes, int chan)</function>
- </para>
- <para>
- Prepare to start a DMA transfer. This function must be
- called to set up the DMA controller before actually
- starting transfer on the device. It checks that the
- buffer is contiguous and falls into the ISA memory
- range, if not then the bounce buffer is automatically
- used. If bounce buffer is required but not set up by
- <function>isa_dmainit()</function> or too small for
- the requested transfer size then the system will
- panic. In case of a write request with bounce buffer
- the data will be automatically copied to the bounce
- buffer.
- </para>
- </listitem>
- <listitem>
- <para>flags - a bitmask determining the type of operation to
- be done. The direction bits B_READ and B_WRITE are mutually
- exclusive.
- </para>
- <!-- <blockquote> -->
- <itemizedlist>
- <listitem>
- <para>
- B_READ - read from the ISA bus into memory
- </para>
- </listitem>
- <listitem>
- <para>
- B_WRITE - write from the memory to the ISA bus
- </para>
- </listitem>
- <listitem>
- <para>
- B_RAW - if set then the DMA controller will remember
- the buffer and after the end of transfer will
- automatically re-initialize itself to repeat transfer
- of the same buffer again (of course, the driver may
- change the data in the buffer before initiating
- another transfer in the device). If not set then the
- parameters will work only for one transfer, and
- <function>isa_dmastart()</function> will have to be
- called again before initiating the next
- transfer. Using B_RAW makes sense only if the bounce
- buffer is not used.
- </para>
- </listitem>
- </itemizedlist>
-<!-- </blockquote> -->
- </listitem>
- <listitem>
- <para>
- addr - virtual address of the buffer
- </para>
- </listitem>
- <listitem>
- <para>
- nbytes - length of the buffer. Must be less or equal to
- 64KB. Length of 0 is not allowed: the DMA controller will
- understand it as 64KB while the kernel code will
- understand it as 0 and that would cause unpredictable
- effects. For channels number 4 and higher the length must
- be even because these channels transfer 2 bytes at a
- time. In case of an odd length the last byte will not be
- transferred.
- </para>
- </listitem>
- <listitem>
- <para>
- chan - channel number
- </para>
- </listitem>
-
- <listitem>
- <para>
- <function>void isa_dmadone(int flags, caddr_t addr, int
- nbytes, int chan)</function>
- </para>
- <para>
- Synchronize the memory after device reports that transfer
- is done. If that was a read operation with a bounce buffer
- then the data will be copied from the bounce buffer to the
- original buffer. Arguments are the same as for
- <function>isa_dmastart()</function>. Flag B_RAW is
- permitted but it does not affect
- <function>isa_dmadone()</function> in any way.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <function>int isa_dmastatus(int channel_number)</function>
- </para>
- <para>
- Returns the number of bytes left in the current transfer
- to be transferred. In case the flag B_READ was set in
- <function>isa_dmastart()</function> the number returned
- will never be equal to zero. At the end of transfer it
- will be automatically reset back to the length of
- buffer. The normal use is to check the number of bytes
- left after the device signals that the transfer is
- completed. If the number of bytes is not 0 then something
- probably went wrong with that transfer.
- </para>
- </listitem>
-
- <listitem>
- <para>
- <function>int isa_dmastop(int channel_number)</function>
- </para>
- <para>
- Aborts the current transfer and returns the number of
- bytes left untransferred.
- </para>
- </listitem>
- </itemizedlist>
- </sect1>
-
- <sect1 xml:id="isa-driver-probe">
- <title>xxx_isa_probe</title>
- <!-- Section marked up by Wylie -->
-
- <para>
- This function probes if a device is present. If the driver
- supports auto-detection of some part of device configuration
- (such as interrupt vector or memory address) this
- auto-detection must be done in this routine.
- </para>
-
- <para>
- As for any other bus, if the device cannot be detected or
- is detected but failed the self-test or some other problem
- happened then it returns a positive value of error. The
- value <errorname>ENXIO</errorname> must be returned if the device is not
- present. Other error values may mean other conditions. Zero
- or negative values mean success. Most of the drivers return
- zero as success.
- </para>
-
- <para>
- The negative return values are used when a PnP device
- supports multiple interfaces. For example, an older
- compatibility interface and a newer advanced interface which
- are supported by different drivers. Then both drivers would
- detect the device. The driver which returns a higher value
- in the probe routine takes precedence (in other words, the
- driver returning 0 has highest precedence, one returning -1
- is next, one returning -2 is after it and so on). In result
- the devices which support only the old interface will be
- handled by the old driver (which should return -1 from the
- probe routine) while the devices supporting the new
- interface as well will be handled by the new driver (which
- should return 0 from the probe routine).
- </para>
-
- <para>
- The device descriptor struct xxx_softc is allocated by the
- system before calling the probe routine. If the probe
- routine returns an error the descriptor will be
- automatically deallocated by the system. So if a probing
- error occurs the driver must make sure that all the
- resources it used during probe are deallocated and that
- nothing keeps the descriptor from being safely
- deallocated. If the probe completes successfully the
- descriptor will be preserved by the system and later passed
- to the routine <function>xxx_isa_attach()</function>. If a
- driver returns a negative value it can not be sure that it
- will have the highest priority and its attach routine will
- be called. So in this case it also must release all the
- resources before returning and if necessary allocate them
- again in the attach routine. When
- <function>xxx_isa_probe()</function> returns 0 releasing the
- resources before returning is also a good idea and a
- well-behaved driver should do so. But in cases where there is
- some problem with releasing the resources the driver is
- allowed to keep resources between returning 0 from the probe
- routine and execution of the attach routine.
- </para>
-
- <para>
- A typical probe routine starts with getting the device
- descriptor and unit:
- </para>
-
- <programlisting> struct xxx_softc *sc = device_get_softc(dev);
- int unit = device_get_unit(dev);
- int pnperror;
- int error = 0;
-
- sc-&gt;dev = dev; /* link it back */
- sc-&gt;unit = unit; </programlisting>
-
- <para>
- Then check for the PnP devices. The check is carried out by
- a table containing the list of PnP IDs supported by this
- driver and human-readable descriptions of the device models
- corresponding to these IDs.
- </para>
-
- <programlisting>
- pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,
- xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;
- </programlisting>
-
- <para>
- The logic of ISA_PNP_PROBE is the following: If this card
- (device unit) was not detected as PnP then ENOENT will be
- returned. If it was detected as PnP but its detected ID does
- not match any of the IDs in the table then ENXIO is
- returned. Finally, if it has PnP support and it matches on
- of the IDs in the table, 0 is returned and the appropriate
- description from the table is set by
- <function>device_set_desc()</function>.
- </para>
-
- <para>
- If a driver supports only PnP devices then the condition
- would look like:
- </para>
-
- <programlisting> if(pnperror != 0)
- return pnperror; </programlisting>
-
- <para>
- No special treatment is required for the drivers which do not
- support PnP because they pass an empty PnP ID table and will
- always get ENXIO if called on a PnP card.
- </para>
-
- <para>
- The probe routine normally needs at least some minimal set
- of resources, such as I/O port number to find the card and
- probe it. Depending on the hardware the driver may be able
- to discover the other necessary resources automatically. The
- PnP devices have all the resources pre-set by the PnP
- subsystem, so the driver does not need to discover them by
- itself.
- </para>
-
- <para>
- Typically the minimal information required to get access to
- the device is the I/O port number. Then some devices allow
- to get the rest of information from the device configuration
- registers (though not all devices do that). So first we try
- to get the port start value:
- </para>
-
- <programlisting> sc-&gt;port0 = bus_get_resource_start(dev,
- SYS_RES_IOPORT, 0 /*rid*/); if(sc-&gt;port0 == 0) return ENXIO;
- </programlisting>
-
- <para>
- The base port address is saved in the structure softc for
- future use. If it will be used very often then calling the
- resource function each time would be prohibitively slow. If
- we do not get a port we just return an error. Some device
- drivers can instead be clever and try to probe all the
- possible ports, like this:
- </para>
-
- <programlisting>
- /* table of all possible base I/O port addresses for this device */
- static struct xxx_allports {
- u_short port; /* port address */
- short used; /* flag: if this port is already used by some unit */
- } xxx_allports = {
- { 0x300, 0 },
- { 0x320, 0 },
- { 0x340, 0 },
- { 0, 0 } /* end of table */
- };
-
- ...
- int port, i;
- ...
-
- port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);
- if(port !=0 ) {
- for(i=0; xxx_allports[i].port!=0; i++) {
- if(xxx_allports[i].used || xxx_allports[i].port != port)
- continue;
-
- /* found it */
- xxx_allports[i].used = 1;
- /* do probe on a known port */
- return xxx_really_probe(dev, port);
- }
- return ENXIO; /* port is unknown or already used */
- }
-
- /* we get here only if we need to guess the port */
- for(i=0; xxx_allports[i].port!=0; i++) {
- if(xxx_allports[i].used)
- continue;
-
- /* mark as used - even if we find nothing at this port
- * at least we won't probe it in future
- */
- xxx_allports[i].used = 1;
-
- error = xxx_really_probe(dev, xxx_allports[i].port);
- if(error == 0) /* found a device at that port */
- return 0;
- }
- /* probed all possible addresses, none worked */
- return ENXIO;</programlisting>
-
- <para>
- Of course, normally the driver's
- <function>identify()</function> routine should be used for
- such things. But there may be one valid reason why it may be
- better to be done in <function>probe()</function>: if this
- probe would drive some other sensitive device crazy. The
- probe routines are ordered with consideration of the
- <literal>sensitive</literal> flag: the sensitive devices get probed first and
- the rest of the devices later. But the
- <function>identify()</function> routines are called before
- any probes, so they show no respect to the sensitive devices
- and may upset them.
- </para>
-
- <para>
- Now, after we got the starting port we need to set the port
- count (except for PnP devices) because the kernel does not
- have this information in the configuration file.
- </para>
-
- <programlisting>
- if(pnperror /* only for non-PnP devices */
- &#38;&#38; bus_set_resource(dev, SYS_RES_IOPORT, 0, sc-&gt;port0,
- XXX_PORT_COUNT)&lt;0)
- return ENXIO;</programlisting>
-
- <para>
- Finally allocate and activate a piece of port address space
- (special values of start and end mean <quote>use those we set by
- <function>bus_set_resource()</function></quote>):
- </para>
-
- <programlisting>
- sc-&gt;port0_rid = 0;
- sc-&gt;port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,
- &#38;sc-&gt;port0_rid,
- /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
-
- if(sc-&gt;port0_r == NULL)
- return ENXIO;</programlisting>
-
- <para>
- Now having access to the port-mapped registers we can poke
- the device in some way and check if it reacts like it is
- expected to. If it does not then there is probably some
- other device or no device at all at this address.
- </para>
-
- <para>
- Normally drivers do not set up the interrupt handlers until
- the attach routine. Instead they do probes in the polling
- mode using the <function>DELAY()</function> function for
- timeout. The probe routine must never hang forever, all the
- waits for the device must be done with timeouts. If the
- device does not respond within the time it is probably broken
- or misconfigured and the driver must return error. When
- determining the timeout interval give the device some extra
- time to be on the safe side: although
- <function>DELAY()</function> is supposed to delay for the
- same amount of time on any machine it has some margin of
- error, depending on the exact CPU.
- </para>
-
- <para>
- If the probe routine really wants to check that the
- interrupts really work it may configure and probe the
- interrupts too. But that is not recommended.
- </para>
-
- <programlisting>
- /* implemented in some very device-specific way */
- if(error = xxx_probe_ports(sc))
- goto bad; /* will deallocate the resources before returning */
- </programlisting>
-
- <para>
- The function <function>xxx_probe_ports()</function> may also
- set the device description depending on the exact model of
- device it discovers. But if there is only one supported
- device model this can be as well done in a hardcoded way.
- Of course, for the PnP devices the PnP support sets the
- description from the table automatically.
- </para>
-
-
- <programlisting> if(pnperror)
- device_set_desc(dev, "Our device model 1234");
- </programlisting>
-
- <para>
- Then the probe routine should either discover the ranges of
- all the resources by reading the device configuration
- registers or make sure that they were set explicitly by the
- user. We will consider it with an example of on-board
- memory. The probe routine should be as non-intrusive as
- possible, so allocation and check of functionality of the
- rest of resources (besides the ports) would be better left
- to the attach routine.
- </para>
-
- <para>
- The memory address may be specified in the kernel
- configuration file or on some devices it may be
- pre-configured in non-volatile configuration registers. If
- both sources are available and different, which one should
- be used? Probably if the user bothered to set the address
- explicitly in the kernel configuration file they know what
- they are doing and this one should take precedence. An
- example of implementation could be:
- </para>
- <programlisting>
- /* try to find out the config address first */
- sc-&gt;mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);
- if(sc-&gt;mem0_p == 0) { /* nope, not specified by user */
- sc-&gt;mem0_p = xxx_read_mem0_from_device_config(sc);
-
-
- if(sc-&gt;mem0_p == 0)
- /* can't get it from device config registers either */
- goto bad;
- } else {
- if(xxx_set_mem0_address_on_device(sc) &lt; 0)
- goto bad; /* device does not support that address */
- }
-
- /* just like the port, set the memory size,
- * for some devices the memory size would not be constant
- * but should be read from the device configuration registers instead
- * to accommodate different models of devices. Another option would
- * be to let the user set the memory size as "msize" configuration
- * resource which will be automatically handled by the ISA bus.
- */
- if(pnperror) { /* only for non-PnP devices */
- sc-&gt;mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
- if(sc-&gt;mem0_size == 0) /* not specified by user */
- sc-&gt;mem0_size = xxx_read_mem0_size_from_device_config(sc);
-
- if(sc-&gt;mem0_size == 0) {
- /* suppose this is a very old model of device without
- * auto-configuration features and the user gave no preference,
- * so assume the minimalistic case
- * (of course, the real value will vary with the driver)
- */
- sc-&gt;mem0_size = 8*1024;
- }
-
- if(xxx_set_mem0_size_on_device(sc) &lt; 0)
- goto bad; /* device does not support that size */
-
- if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,
- sc-&gt;mem0_p, sc-&gt;mem0_size)&lt;0)
- goto bad;
- } else {
- sc-&gt;mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
- } </programlisting>
-
- <para>
- Resources for IRQ and DRQ are easy to check by analogy.
- </para>
-
- <para>
- If all went well then release all the resources and return success.
- </para>
-
- <programlisting> xxx_free_resources(sc);
- return 0;</programlisting>
-
- <para>
- Finally, handle the troublesome situations. All the
- resources should be deallocated before returning. We make
- use of the fact that before the structure softc is passed to
- us it gets zeroed out, so we can find out if some resource
- was allocated: then its descriptor is non-zero.
- </para>
-
- <programlisting> bad:
-
- xxx_free_resources(sc);
- if(error)
- return error;
- else /* exact error is unknown */
- return ENXIO;</programlisting>
-
- <para>
- That would be all for the probe routine. Freeing of
- resources is done from multiple places, so it is moved to a
- function which may look like:
- </para>
-
-<programlisting>static void
- xxx_free_resources(sc)
- struct xxx_softc *sc;
- {
- /* check every resource and free if not zero */
-
- /* interrupt handler */
- if(sc-&gt;intr_r) {
- bus_teardown_intr(sc-&gt;dev, sc-&gt;intr_r, sc-&gt;intr_cookie);
- bus_release_resource(sc-&gt;dev, SYS_RES_IRQ, sc-&gt;intr_rid,
- sc-&gt;intr_r);
- sc-&gt;intr_r = 0;
- }
-
- /* all kinds of memory maps we could have allocated */
- if(sc-&gt;data_p) {
- bus_dmamap_unload(sc-&gt;data_tag, sc-&gt;data_map);
- sc-&gt;data_p = 0;
- }
- if(sc-&gt;data) { /* sc-&gt;data_map may be legitimately equal to 0 */
- /* the map will also be freed */
- bus_dmamem_free(sc-&gt;data_tag, sc-&gt;data, sc-&gt;data_map);
- sc-&gt;data = 0;
- }
- if(sc-&gt;data_tag) {
- bus_dma_tag_destroy(sc-&gt;data_tag);
- sc-&gt;data_tag = 0;
- }
-
- ... free other maps and tags if we have them ...
-
- if(sc-&gt;parent_tag) {
- bus_dma_tag_destroy(sc-&gt;parent_tag);
- sc-&gt;parent_tag = 0;
- }
-
- /* release all the bus resources */
- if(sc-&gt;mem0_r) {
- bus_release_resource(sc-&gt;dev, SYS_RES_MEMORY, sc-&gt;mem0_rid,
- sc-&gt;mem0_r);
- sc-&gt;mem0_r = 0;
- }
- ...
- if(sc-&gt;port0_r) {
- bus_release_resource(sc-&gt;dev, SYS_RES_IOPORT, sc-&gt;port0_rid,
- sc-&gt;port0_r);
- sc-&gt;port0_r = 0;
- }
- }</programlisting>
-
- </sect1>
-
- <sect1 xml:id="isa-driver-attach">
- <title>xxx_isa_attach</title>
- <!-- Section Marked up by Wylie -->
-
- <para>The attach routine actually connects the driver to the
- system if the probe routine returned success and the system
- had chosen to attach that driver. If the probe routine
- returned 0 then the attach routine may expect to receive the
- device structure softc intact, as it was set by the probe
- routine. Also if the probe routine returns 0 it may expect
- that the attach routine for this device shall be called at
- some point in the future. If the probe routine returns a
- negative value then the driver may make none of these
- assumptions.
- </para>
-
- <para>The attach routine returns 0 if it completed successfully or
- error code otherwise.
- </para>
-
- <para>The attach routine starts just like the probe routine,
- with getting some frequently used data into more accessible
- variables.
- </para>
-
- <programlisting> struct xxx_softc *sc = device_get_softc(dev);
- int unit = device_get_unit(dev);
- int error = 0;</programlisting>
-
- <para>Then allocate and activate all the necessary
- resources. As normally the port range will be released
- before returning from probe, it has to be allocated
- again. We expect that the probe routine had properly set all
- the resource ranges, as well as saved them in the structure
- softc. If the probe routine had left some resource allocated
- then it does not need to be allocated again (which would be
- considered an error).
- </para>
-
- <programlisting> sc-&gt;port0_rid = 0;
- sc-&gt;port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &#38;sc-&gt;port0_rid,
- /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
-
- if(sc-&gt;port0_r == NULL)
- return ENXIO;
-
- /* on-board memory */
- sc-&gt;mem0_rid = 0;
- sc-&gt;mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &#38;sc-&gt;mem0_rid,
- /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
-
- if(sc-&gt;mem0_r == NULL)
- goto bad;
-
- /* get its virtual address */
- sc-&gt;mem0_v = rman_get_virtual(sc-&gt;mem0_r);</programlisting>
-
- <para>The DMA request channel (DRQ) is allocated likewise. To
- initialize it use functions of the
- <function>isa_dma*()</function> family. For example:
- </para>
-
- <para><function>isa_dmacascade(sc-&gt;drq0);</function></para>
-
- <para>The interrupt request line (IRQ) is a bit
- special. Besides allocation the driver's interrupt handler
- should be associated with it. Historically in the old ISA
- drivers the argument passed by the system to the interrupt
- handler was the device unit number. But in modern drivers
- the convention suggests passing the pointer to structure
- softc. The important reason is that when the structures
- softc are allocated dynamically then getting the unit number
- from softc is easy while getting softc from the unit number is
- difficult. Also this convention makes the drivers for
- different buses look more uniform and allows them to share
- the code: each bus gets its own probe, attach, detach and
- other bus-specific routines while the bulk of the driver
- code may be shared among them.
- </para>
-
- <programlisting>
- sc-&gt;intr_rid = 0;
- sc-&gt;intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &#38;sc-&gt;intr_rid,
- /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);
-
- if(sc-&gt;intr_r == NULL)
- goto bad;
-
- /*
- * XXX_INTR_TYPE is supposed to be defined depending on the type of
- * the driver, for example as INTR_TYPE_CAM for a CAM driver
- */
- error = bus_setup_intr(dev, sc-&gt;intr_r, XXX_INTR_TYPE,
- (driver_intr_t *) xxx_intr, (void *) sc, &#38;sc-&gt;intr_cookie);
- if(error)
- goto bad;
-
- </programlisting>
-
-
- <para>If the device needs to make DMA to the main memory then
- this memory should be allocated like described before:
- </para>
-
- <programlisting> error=bus_dma_tag_create(NULL, /*alignment*/ 4,
- /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,
- /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,
- /*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,
- /*nsegments*/ BUS_SPACE_UNRESTRICTED,
- /*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,
- &#38;sc-&gt;parent_tag);
- if(error)
- goto bad;
-
- /* many things get inherited from the parent tag
- * sc-&gt;data is supposed to point to the structure with the shared data,
- * for example for a ring buffer it could be:
- * struct {
- * u_short rd_pos;
- * u_short wr_pos;
- * char bf[XXX_RING_BUFFER_SIZE]
- * } *data;
- */
- error=bus_dma_tag_create(sc-&gt;parent_tag, 1,
- 0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,
- /*maxsize*/ sizeof(* sc-&gt;data), /*nsegments*/ 1,
- /*maxsegsz*/ sizeof(* sc-&gt;data), /*flags*/ 0,
- &#38;sc-&gt;data_tag);
- if(error)
- goto bad;
-
- error = bus_dmamem_alloc(sc-&gt;data_tag, &#38;sc-&gt;data, /* flags*/ 0,
- &#38;sc-&gt;data_map);
- if(error)
- goto bad;
-
- /* xxx_alloc_callback() just saves the physical address at
- * the pointer passed as its argument, in this case &#38;sc-&gt;data_p.
- * See details in the section on bus memory mapping.
- * It can be implemented like:
- *
- * static void
- * xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,
- * int nseg, int error)
- * {
- * *(bus_addr_t *)arg = seg[0].ds_addr;
- * }
- */
- bus_dmamap_load(sc-&gt;data_tag, sc-&gt;data_map, (void *)sc-&gt;data,
- sizeof (* sc-&gt;data), xxx_alloc_callback, (void *) &#38;sc-&gt;data_p,
- /*flags*/0);</programlisting>
-
-
- <para>After all the necessary resources are allocated the
- device should be initialized. The initialization may include
- testing that all the expected features are functional.</para>
-
- <programlisting> if(xxx_initialize(sc) &lt; 0)
- goto bad; </programlisting>
-
-
- <para>The bus subsystem will automatically print on the
- console the device description set by probe. But if the
- driver wants to print some extra information about the
- device it may do so, for example:</para>
-
- <programlisting>
- device_printf(dev, "has on-card FIFO buffer of %d bytes\n", sc-&gt;fifosize);
- </programlisting>
-
- <para>If the initialization routine experiences any problems
- then printing messages about them before returning error is
- also recommended.</para>
-
- <para>The final step of the attach routine is attaching the
- device to its functional subsystem in the kernel. The exact
- way to do it depends on the type of the driver: a character
- device, a block device, a network device, a CAM SCSI bus
- device and so on.</para>
-
- <para>If all went well then return success.</para>
-
- <programlisting> error = xxx_attach_subsystem(sc);
- if(error)
- goto bad;
-
- return 0; </programlisting>
-
- <para>Finally, handle the troublesome situations. All the
- resources should be deallocated before returning an
- error. We make use of the fact that before the structure
- softc is passed to us it gets zeroed out, so we can find out
- if some resource was allocated: then its descriptor is
- non-zero.</para>
-
- <programlisting> bad:
-
- xxx_free_resources(sc);
- if(error)
- return error;
- else /* exact error is unknown */
- return ENXIO;</programlisting>
-
- <para>That would be all for the attach routine.</para>
-
- </sect1>
-
-
- <sect1 xml:id="isa-driver-detach">
- <title>xxx_isa_detach</title>
-
- <para>
- If this function is present in the driver and the driver is
- compiled as a loadable module then the driver gets the
- ability to be unloaded. This is an important feature if the
- hardware supports hot plug. But the ISA bus does not support
- hot plug, so this feature is not particularly important for
- the ISA devices. The ability to unload a driver may be
- useful when debugging it, but in many cases installation of
- the new version of the driver would be required only after
- the old version somehow wedges the system and a reboot will be
- needed anyway, so the efforts spent on writing the detach
- routine may not be worth it. Another argument that
- unloading would allow upgrading the drivers on a production
- machine seems to be mostly theoretical. Installing a new
- version of a driver is a dangerous operation which should
- never be performed on a production machine (and which is not
- permitted when the system is running in secure mode). Still,
- the detach routine may be provided for the sake of
- completeness.
- </para>
-
- <para>
- The detach routine returns 0 if the driver was successfully
- detached or the error code otherwise.
- </para>
-
- <para>
- The logic of detach is a mirror of the attach. The first
- thing to do is to detach the driver from its kernel
- subsystem. If the device is currently open then the driver
- has two choices: refuse to be detached or forcibly close and
- proceed with detach. The choice used depends on the ability
- of the particular kernel subsystem to do a forced close and
- on the preferences of the driver's author. Generally the
- forced close seems to be the preferred alternative.
- <programlisting> struct xxx_softc *sc = device_get_softc(dev);
- int error;
-
- error = xxx_detach_subsystem(sc);
- if(error)
- return error;</programlisting>
- </para>
- <para>
- Next the driver may want to reset the hardware to some
- consistent state. That includes stopping any ongoing
- transfers, disabling the DMA channels and interrupts to
- avoid memory corruption by the device. For most of the
- drivers this is exactly what the shutdown routine does, so
- if it is included in the driver we can just call it.
- </para>
- <para><function>xxx_isa_shutdown(dev);</function></para>
-
- <para>
- And finally release all the resources and return success.
- <programlisting> xxx_free_resources(sc);
- return 0;</programlisting>
-
- </para>
- </sect1>
-
- <sect1 xml:id="isa-driver-shutdown">
- <title>xxx_isa_shutdown</title>
-
- <para>
- This routine is called when the system is about to be shut
- down. It is expected to bring the hardware to some
- consistent state. For most of the ISA devices no special
- action is required, so the function is not really necessary
- because the device will be re-initialized on reboot
- anyway. But some devices have to be shut down with a special
- procedure, to make sure that they will be properly detected
- after soft reboot (this is especially true for many devices
- with proprietary identification protocols). In any case
- disabling DMA and interrupts in the device registers and
- stopping any ongoing transfers is a good idea. The exact
- action depends on the hardware, so we do not consider it here
- in any detail.
- </para>
- </sect1>
-
- <sect1 xml:id="isa-driver-intr">
- <title>xxx_intr</title>
-
- <indexterm><primary>interrupt handler</primary></indexterm>
-
- <para>
- The interrupt handler is called when an interrupt is
- received which may be from this particular device. The ISA
- bus does not support interrupt sharing (except in some special
- cases) so in practice if the interrupt handler is called
- then the interrupt almost for sure came from its
- device. Still, the interrupt handler must poll the device
- registers and make sure that the interrupt was generated by
- its device. If not it should just return.
- </para>
-
- <para>
- The old convention for the ISA drivers was getting the
- device unit number as an argument. This is obsolete, and the
- new drivers receive whatever argument was specified for them
- in the attach routine when calling
- <function>bus_setup_intr()</function>. By the new convention
- it should be the pointer to the structure softc. So the
- interrupt handler commonly starts as:
- </para>
-
- <programlisting>
- static void
- xxx_intr(struct xxx_softc *sc)
- {
-
- </programlisting>
-
- <para>
- It runs at the interrupt priority level specified by the
- interrupt type parameter of
- <function>bus_setup_intr()</function>. That means that all
- the other interrupts of the same type as well as all the
- software interrupts are disabled.
- </para>
-
- <para>
- To avoid races it is commonly written as a loop:
- </para>
-
- <programlisting>
- while(xxx_interrupt_pending(sc)) {
- xxx_process_interrupt(sc);
- xxx_acknowledge_interrupt(sc);
- } </programlisting>
-
- <para>
- The interrupt handler has to acknowledge interrupt to the
- device only but not to the interrupt controller, the system
- takes care of the latter.
- </para>
-
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/jail/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/jail/chapter.xml
deleted file mode 100644
index a54476d45b..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/jail/chapter.xml
+++ /dev/null
@@ -1,794 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD$
--->
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:id="jail">
- <info>
- <title>The Jail Subsystem</title>
-
- <author>
- <personname>
- <firstname>Evan</firstname>
- <surname>Sarmiento</surname>
- </personname>
- <affiliation>
- <address>
- <email>evms@cs.bu.edu</email>
- </address>
- </affiliation>
- </author>
- <copyright>
- <year>2001</year>
- <holder role="mailto:evms@cs.bu.edu">Evan Sarmiento</holder>
- </copyright>
- </info>
-
- <indexterm><primary>security</primary></indexterm>
- <indexterm><primary>Jail</primary></indexterm>
- <indexterm><primary>root</primary></indexterm>
-
- <para>On most &unix; systems, <literal>root</literal> has omnipotent
- power. This promotes insecurity. If an attacker gained
- <literal>root</literal> on a system, he would have every function
- at his fingertips. In FreeBSD there are sysctls which dilute the
- power of <literal>root</literal>, in order to minimize the damage
- caused by an attacker. Specifically, one of these functions is
- called <literal>secure levels</literal>. Similarly, another
- function which is present from FreeBSD 4.0 and onward, is a
- utility called &man.jail.8;. <application>Jail</application>
- chroots an environment and sets certain restrictions on processes
- which are forked within the <application>jail</application>. For
- example, a jailed process cannot affect processes outside the
- <application>jail</application>, utilize certain system calls, or
- inflict any damage on the host environment.</para>
-
- <para><application>Jail</application> is becoming the new security
- model. People are running potentially vulnerable servers such as
- <application>Apache</application>,
- <application>BIND</application>, and
- <application>sendmail</application> within jails, so that if an
- attacker gains <literal>root</literal> within the
- <application>jail</application>, it is only an annoyance, and not
- a devastation. This article mainly focuses on the internals
- (source code) of <application>jail</application>. For information
- on how to set up a jail see the <link
- xlink:href="&url.books.handbook;/jails.html">handbook entry on
- jails</link>.</para>
-
- <sect1 xml:id="jail-arch">
- <title>Architecture</title>
-
- <para><application>Jail</application> 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 <application>jail</application> is implemented within
- the kernel.</para>
-
- <sect2>
- <title>Userland Code</title>
-
- <indexterm><primary>Jail</primary>
- <secondary>Userland Program</secondary></indexterm>
-
- <para>The source for the userland
- <application>jail</application> is located in
- <filename>/usr/src/usr.sbin/jail</filename>, consisting of one
- file, <filename>jail.c</filename>. The program takes these
- arguments: the path of the <application>jail</application>,
- hostname, IP address, and the command to be executed.</para>
-
- <sect3>
- <title>Data Structures</title>
-
- <para>In <filename>jail.c</filename>, the first thing I would
- note is the declaration of an important structure
- <literal>struct jail j;</literal> which was included from
- <filename>/usr/include/sys/jail.h</filename>.</para>
-
- <para>The definition of the <literal>jail</literal> structure
- is:</para>
-
- <programlisting><filename>/usr/include/sys/jail.h</filename>:
-
-struct jail {
- u_int32_t version;
- char *path;
- char *hostname;
- u_int32_t ip_number;
-};</programlisting>
-
- <para>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.</para>
-
- <programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>
-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(&amp;j, 0, sizeof(j));
-j.version = 0;
-j.path = path;
-j.hostname = argv[1];</programlisting>
- </sect3>
-
- <sect3>
- <title>Networking</title>
-
- <para>One of the arguments passed to the &man.jail.8; program
- is an IP address with which the
- <application>jail</application> can be accessed over the
- network. &man.jail.8; translates the IP address given into
- host byte order and then stores it in <literal>j</literal>
- (the <literal>jail</literal> structure).</para>
-
- <programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>:
-struct in_addr in;
-...
-if (inet_aton(argv[2], &amp;in) == 0)
- errx(1, "Could not make sense of ip-number: %s", argv[2]);
-j.ip_number = ntohl(in.s_addr);</programlisting>
-
- <para>The &man.inet.aton.3; function "interprets the specified
- character string as an Internet address, placing the address
- into the structure provided." The
- <literal>ip_number</literal> member in the
- <literal>jail</literal> structure is set only when the IP
- address placed onto the <literal>in</literal> structure by
- &man.inet.aton.3; is translated into host byte order by
- &man.ntohl.3;.</para>
- </sect3>
-
- <sect3>
- <title>Jailing the Process</title>
-
- <para>Finally, the userland program jails the process.
- <application>Jail</application> now becomes an imprisoned
- process itself and then executes the command given using
- &man.execv.3;.</para>
-
- <programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>
-i = jail(&amp;j);
-...
-if (execv(argv[3], argv + 3) != 0)
- err(1, "execv: %s", argv[3]);</programlisting>
-
- <para>As you can see, the <literal>jail()</literal> function
- is called, and its argument is the <literal>jail</literal>
- structure which has been filled with the arguments given to
- the program. Finally, the program you specify is executed.
- I will now discuss how <application>jail</application> is
- implemented within the kernel.</para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>Kernel Space</title>
-
- <indexterm><primary>Jail</primary>
- <secondary>Kernel Architecture</secondary></indexterm>
-
- <para>We will now be looking at the file
- <filename>/usr/src/sys/kern/kern_jail.c</filename>. This is
- the file where the &man.jail.2; system call, appropriate
- sysctls, and networking functions are defined.</para>
-
- <sect3>
- <title>Sysctls</title>
-
- <indexterm><primary>sysctl</primary></indexterm>
-
- <para>In <filename>kern_jail.c</filename>, the following
- sysctls are defined:</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
-int jail_set_hostname_allowed = 1;
-SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
- &amp;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,
- &amp;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,
- &amp;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,
- &amp;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,
- &amp;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,
- &amp;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,
- &amp;jail_mount_allowed, 0,
- "Processes in jail can mount/unmount jail-friendly file systems");</programlisting>
-
- <para>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
- <literal>security.jail.set_hostname_allowed</literal>.</para>
- </sect3>
-
- <sect3>
- <title>&man.jail.2; System Call</title>
-
- <para>Like all system calls, the &man.jail.2; system call
- takes two arguments, <literal>struct thread *td</literal>
- and <literal>struct jail_args *uap</literal>.
- <literal>td</literal> is a pointer to the
- <literal>thread</literal> structure which describes the
- calling thread. In this context, <literal>uap</literal> is
- a pointer to the structure in which a pointer to the
- <literal>jail</literal> structure passed by the userland
- <filename>jail.c</filename> is contained. When I described
- the userland program before, you saw that the &man.jail.2;
- system call was given a <literal>jail</literal> structure as
- its own argument.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
-/*
- * struct jail_args {
- * struct jail *jail;
- * };
- */
-int
-jail(struct thread *td, struct jail_args *uap)</programlisting>
-
- <para>Therefore, <literal>uap-&gt;jail</literal> can be used
- to access the <literal>jail</literal> structure which was
- passed to the system call. Next, the system call copies the
- <literal>jail</literal> 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, <literal>uap-&gt;jail</literal>, where to
- store it, <literal>j</literal> and the size of the storage.
- The <literal>jail</literal> structure pointed by
- <literal>uap-&gt;jail</literal> is copied into kernel space
- and is stored in another <literal>jail</literal> structure,
- <literal>j</literal>.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
-error = copyin(uap-&gt;jail, &amp;j, sizeof(j));</programlisting>
-
- <para>There is another important structure defined in
- <filename>jail.h</filename>. It is the
- <literal>prison</literal> structure. The
- <literal>prison</literal> structure is used exclusively
- within kernel space. Here is the definition of the
- <literal>prison</literal> structure.</para>
-
- <programlisting><filename>/usr/include/sys/jail.h</filename>:
-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 */
-};</programlisting>
-
- <para>The &man.jail.2; system call then allocates memory for a
- <literal>prison</literal> structure and copies data between
- the <literal>jail</literal> and <literal>prison</literal>
- structure.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>:
-MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
-...
-error = copyinstr(j.path, &amp;pr-&gt;pr_path, sizeof(pr-&gt;pr_path), 0);
-if (error)
- goto e_killmtx;
-...
-error = copyinstr(j.hostname, &amp;pr-&gt;pr_host, sizeof(pr-&gt;pr_host), 0);
-if (error)
- goto e_dropvnref;
-pr-&gt;pr_ip = j.ip_number;</programlisting>
-
- <para>Next, we will discuss another important system call
- &man.jail.attach.2;, which implements the function to put a
- process into the <application>jail</application>.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>:
-/*
- * struct jail_attach_args {
- * int jid;
- * };
- */
-int
-jail_attach(struct thread *td, struct jail_attach_args *uap)</programlisting>
-
- <para>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.</para>
-
- <para>On FreeBSD, each kernel visible thread is identified by
- its <literal>thread</literal> structure, while the processes
- are described by their <literal>proc</literal> structures.
- You can find the definitions of the
- <literal>thread</literal> and <literal>proc</literal>
- structure in <filename>/usr/include/sys/proc.h</filename>.
- For example, the <literal>td</literal> argument in any
- system call is actually a pointer to the calling thread's
- <literal>thread</literal> structure, as stated before. The
- <literal>td_proc</literal> member in the
- <literal>thread</literal> structure pointed by
- <literal>td</literal> is a pointer to the
- <literal>proc</literal> structure which represents the
- process that contains the thread represented by
- <literal>td</literal>. The <literal>proc</literal>
- structure contains members which can describe the owner's
- identity(<literal>p_ucred</literal>), the process resource
- limits(<literal>p_limit</literal>), and so on. In the
- <literal>ucred</literal> structure pointed by
- <literal>p_ucred</literal> member in the
- <literal>proc</literal> structure, there is a pointer to the
- <literal>prison</literal>
- structure(<literal>cr_prison</literal>).</para>
-
- <programlisting><filename>/usr/include/sys/proc.h:</filename>
-struct thread {
- ...
- struct proc *td_proc;
- ...
-};
-struct proc {
- ...
- struct ucred *p_ucred;
- ...
-};
-<filename>/usr/include/sys/ucred.h</filename>
-struct ucred {
- ...
- struct prison *cr_prison;
- ...
-};</programlisting>
-
- <para>In <filename>kern_jail.c</filename>, the function
- <literal>jail()</literal> then calls function
- <literal>jail_attach()</literal> with a given
- <literal>jid</literal>. And
- <literal>jail_attach()</literal> calls function
- <literal>change_root()</literal> to change the root
- directory of the calling process. The
- <literal>jail_attach()</literal> then creates a new
- <literal>ucred</literal> structure, and attaches the newly
- created <literal>ucred</literal> structure to the calling
- process after it has successfully attached the
- <literal>prison</literal> structure to the
- <literal>ucred</literal> structure. From then on, the
- calling process is recognized as jailed. When the kernel
- routine <literal>jailed()</literal> is called in the kernel
- with the newly created <literal>ucred</literal> structure as
- its argument, it returns 1 to tell that the credential is
- connected with a <application>jail</application>. The
- public ancestor process of all the process forked within the
- <application>jail</application>, 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
- <literal>ucred</literal> structure, therefore it has a
- jailed <literal>ucred</literal> structure.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>
-int
-jail(struct thread *td, struct jail_args *uap)
-{
-...
- struct jail_attach_args jaa;
-...
- error = jail_attach(td, &amp;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-&gt;td_proc;
-...
- pr = prison_find(uap-&gt;jid);
-...
- change_root(pr-&gt;pr_root, td);
-...
- newcred-&gt;cr_prison = pr;
- p-&gt;p_ucred = newcred;
-...
-}</programlisting>
-
- <para>When a process is forked from its parent process, the
- &man.fork.2; system call uses <literal>crhold()</literal> 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.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_fork.c</filename>:
-p2-&gt;p_ucred = crhold(td-&gt;td_ucred);
-...
-td2-&gt;td_ucred = crhold(p2-&gt;p_ucred);</programlisting>
- </sect3>
- </sect2>
- </sect1>
-
- <sect1 xml:id="jail-restrictions">
- <title>Restrictions</title>
-
- <para>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:</para>
-
- <programlisting>if (jailed(td-&gt;td_ucred))
- return (EPERM);</programlisting>
-
- <sect2>
- <title>SysV IPC</title>
-
- <indexterm><primary>System V IPC</primary></indexterm>
-
- <para>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
- <application>jail</application>. One of these sysctls was
- <literal>security.jail.sysvipc_allowed</literal>. By default,
- this sysctl is set to 0. If it were set to 1, it would defeat
- the whole purpose of having a <application>jail</application>;
- privileged users from the <application>jail</application>
- 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.</para>
-
- <para><filename>/usr/src/sys/kern/sysv_msg.c</filename>:</para>
-
- <itemizedlist>
- <listitem>
- <para><literal>msgget(key, msgflg)</literal>:
- <literal>msgget</literal> returns (and possibly creates) a
- message descriptor that designates a message queue for use
- in other functions.</para>
- </listitem>
-
- <listitem>
- <para><literal>msgctl(msgid, cmd, buf)</literal>: Using this
- function, a process can query the status of a message
- descriptor.</para>
- </listitem>
-
- <listitem>
- <para><literal>msgsnd(msgid, msgp, msgsz, msgflg)</literal>:
- <literal>msgsnd</literal> sends a message to a
- process.</para>
- </listitem>
-
- <listitem>
- <para><literal>msgrcv(msgid, msgp, msgsz, msgtyp,
- msgflg)</literal>: a process receives messages using
- this function</para>
- </listitem>
- </itemizedlist>
-
- <para>In each of the system calls corresponding to these
- functions, there is this conditional:</para>
-
- <programlisting><filename>/usr/src/sys/kern/sysv_msg.c</filename>:
-if (!jail_sysvipc_allowed &amp;&amp; jailed(td-&gt;td_ucred))
- return (ENOSYS);</programlisting>
-
- <indexterm><primary>semaphores</primary></indexterm>
-
- <para>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 <application>jail</application>:
- &man.semget.2;, &man.semctl.2; and &man.semop.2;.</para>
-
- <para><filename>/usr/src/sys/kern/sysv_sem.c</filename>:</para>
-
- <itemizedlist>
- <listitem>
- <para><literal>semctl(semid, semnum, cmd, ...)</literal>:
- <literal>semctl</literal> does the specified
- <literal>cmd</literal> on the semaphore queue indicated by
- <literal>semid</literal>.</para></listitem>
-
- <listitem>
- <para><literal>semget(key, nsems, flag)</literal>:
- <literal>semget</literal> creates an array of semaphores,
- corresponding to <literal>key</literal>.</para>
-
- <para><literal>key and flag take on the same meaning as they
- do in msgget.</literal></para>
- </listitem>
-
- <listitem><para><literal>semop(semid, array, nops)</literal>:
- <literal>semop</literal> performs a group of operations
- indicated by <literal>array</literal>, to the set of
- semaphores identified by
- <literal>semid</literal>.</para></listitem>
- </itemizedlist>
-
- <indexterm><primary>shared memory</primary></indexterm>
-
- <para>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;.</para>
-
- <para><filename>/usr/src/sys/kern/sysv_shm.c</filename>:</para>
-
- <itemizedlist>
- <listitem><para><literal>shmctl(shmid, cmd, buf)</literal>:
- <literal>shmctl</literal> does various control operations
- on the shared memory region identified by
- <literal>shmid</literal>.</para>
- </listitem>
-
- <listitem><para><literal>shmget(key, size, flag)</literal>:
- <literal>shmget</literal> accesses or creates a shared
- memory region of <literal>size</literal>
- bytes.</para>
- </listitem>
-
- <listitem><para><literal>shmat(shmid, addr, flag)</literal>:
- <literal>shmat</literal> attaches a shared memory region
- identified by <literal>shmid</literal> to the address
- space of a process.</para>
- </listitem>
-
- <listitem><para><literal>shmdt(addr)</literal>:
- <literal>shmdt</literal> detaches the shared memory region
- previously attached at
- <literal>addr</literal>.</para>
- </listitem>
- </itemizedlist>
- </sect2>
-
- <sect2>
- <title>Sockets</title>
-
- <indexterm><primary>sockets</primary></indexterm>
-
- <para><application>Jail</application> 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
- <literal>security.jail.socket_unixiproute_only</literal> is
- set. If set, sockets are only allowed to be created if the
- family specified is either <literal>PF_LOCAL</literal>,
- <literal>PF_INET</literal> or <literal>PF_ROUTE</literal>.
- Otherwise, it returns an error.</para>
-
- <programlisting><filename>/usr/src/sys/kern/uipc_socket.c</filename>:
-int
-socreate(int dom, struct socket **aso, int type, int proto,
- struct ucred *cred, struct thread *td)
-{
- struct protosw *prp;
-...
- if (jailed(cred) &amp;&amp; jail_socket_unixiproute_only &amp;&amp;
- prp-&gt;pr_domain-&gt;dom_family != PF_LOCAL &amp;&amp;
- prp-&gt;pr_domain-&gt;dom_family != PF_INET &amp;&amp;
- prp-&gt;pr_domain-&gt;dom_family != PF_ROUTE) {
- return (EPROTONOSUPPORT);
- }
-...
-}</programlisting>
- </sect2>
-
- <sect2>
- <title>Berkeley Packet Filter</title>
-
- <indexterm><primary>Berkeley Packet Filter</primary></indexterm>
- <indexterm><primary>data link layer</primary></indexterm>
-
- <para>The <application>Berkeley Packet Filter</application>
- provides a raw interface to data link layers in a protocol
- independent fashion. <application>BPF</application> is now
- controlled by the &man.devfs.8; whether it can be used in a
- jailed environment.</para>
-
- </sect2>
-
- <sect2>
- <title>Protocols</title>
-
- <indexterm><primary>protocols</primary></indexterm>
-
- <para>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
- <literal>nam</literal> parameter is set.
- <literal>nam</literal> is a pointer to a
- <literal>sockaddr</literal> structure, which describes the
- address on which to bind the service. A more exact definition
- is that <literal>sockaddr</literal> "may be used as a template
- for referring to the identifying tag and length of each
- address". In the function
- <literal>in_pcbbind_setup()</literal>, <literal>sin</literal>
- is a pointer to a <literal>sockaddr_in</literal> structure,
- which contains the port, address, length and domain family of
- the socket which is to be bound. Basically, this disallows
- any processes from <application>jail</application> to be able
- to specify the address that does not belong to the
- <application>jail</application> in which the calling process
- exists.</para>
-
- <programlisting><filename>/usr/src/sys/netinet/in_pcb.c</filename>:
-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-&gt;sin_addr.s_addr != INADDR_ANY)
- if (prison_ip(cred, 0, &amp;sin-&gt;sin_addr.s_addr))
- return(EINVAL);
- ...
- if (lport) {
- ...
- if (prison &amp;&amp; prison_ip(cred, 0, &amp;sin-&gt;sin_addr.s_addr))
- return (EADDRNOTAVAIL);
- ...
- }
- }
- if (lport == 0) {
- ...
- if (laddr.s_addr != INADDR_ANY)
- if (prison_ip(cred, 0, &amp;laddr.s_addr))
- return (EINVAL);
- ...
- }
-...
- if (prison_ip(cred, 0, &amp;laddr.s_addr))
- return (EINVAL);
-...
-}</programlisting>
-
- <para>You might be wondering what function
- <literal>prison_ip()</literal> does.
- <literal>prison_ip()</literal> is given three arguments, a
- pointer to the credential(represented by
- <literal>cred</literal>), any flags, and an IP address. It
- returns 1 if the IP address does NOT belong to the
- <application>jail</application> or 0 otherwise. As you can
- see from the code, if it is indeed an IP address not belonging
- to the <application>jail</application>, the protocol is not
- allowed to bind to that address.</para>
-
- <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
-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-&gt;cr_prison-&gt;pr_ip;
- else
- *ip = htonl(cred-&gt;cr_prison-&gt;pr_ip);
- return (0);
- }
- if (tmp == INADDR_LOOPBACK) {
- if (flag)
- *ip = cred-&gt;cr_prison-&gt;pr_ip;
- else
- *ip = htonl(cred-&gt;cr_prison-&gt;pr_ip);
- return (0);
- }
- if (cred-&gt;cr_prison-&gt;pr_ip != tmp)
- return (1);
- return (0);
-}</programlisting>
- </sect2>
-
- <sect2>
- <title>Filesystem</title>
-
- <indexterm><primary>filesystem</primary></indexterm>
-
- <para>Even <literal>root</literal> users within the
- <application>jail</application> 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.</para>
-
- <programlisting><filename>/usr/src/sys/ufs/ufs/ufs_vnops.c:</filename>
-static int
-ufs_setattr(ap)
- ...
-{
- ...
- if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
- if (ip-&gt;i_flags
- &amp; (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
- error = securelevel_gt(cred, 0);
- if (error)
- return (error);
- }
- ...
- }
-}
-<filename>/usr/src/sys/kern/kern_priv.c</filename>
-int
-priv_check_cred(struct ucred *cred, int priv, int flags)
-{
- ...
- error = prison_priv_check(cred, priv);
- if (error)
- return (error);
- ...
-}
-<filename>/usr/src/sys/kern/kern_jail.c</filename>
-int
-prison_priv_check(struct ucred *cred, int priv)
-{
- ...
- switch (priv) {
- ...
- case PRIV_VFS_SYSFLAGS:
- if (jail_chflags_allowed)
- return (0);
- else
- return (EPERM);
- ...
- }
- ...
-}</programlisting>
- </sect2>
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/kobj/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/kobj/chapter.xml
deleted file mode 100644
index e52d1603d4..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/kobj/chapter.xml
+++ /dev/null
@@ -1,304 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- The FreeBSD Documentation Project
-
- $FreeBSD$
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="kernel-objects">
- <title>Kernel Objects</title>
-
- <indexterm><primary>Kernel Objects</primary></indexterm>
- <indexterm><primary>Object-Oriented</primary></indexterm>
- <indexterm><primary>binary compatibility</primary></indexterm>
- <para>Kernel Objects, or <firstterm>Kobj</firstterm> provides an
- object-oriented C programming system for the kernel. As such the
- data being operated on carries the description of how to operate
- on it. This allows operations to be added and removed from an
- interface at run time and without breaking binary
- compatibility.</para>
-
- <sect1 xml:id="kernel-objects-term">
- <title>Terminology</title>
-
- <indexterm><primary>object</primary></indexterm>
- <indexterm><primary>method</primary></indexterm>
- <indexterm><primary>class</primary></indexterm>
- <indexterm><primary>interface</primary></indexterm>
-
- <variablelist>
- <varlistentry>
- <term>Object</term>
- <listitem><para>A set of data - data structure - data
- allocation.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Method</term>
- <listitem>
- <para>An operation - function.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Class</term>
- <listitem>
- <para>One or more methods.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Interface</term>
- <listitem>
- <para>A standard set of one or more methods.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-
- <sect1 xml:id="kernel-objects-operation">
- <title>Kobj Operation</title>
-
- <para>Kobj works by generating descriptions of methods. Each
- description holds a unique id as well as a default function. The
- description's address is used to uniquely identify the method
- within a class' method table.</para>
-
- <para>A class is built by creating a method table associating one
- or more functions with method descriptions. Before use the class
- is compiled. The compilation allocates a cache and associates it
- with the class. A unique id is assigned to each method
- description within the method table of the class if not already
- done so by another referencing class compilation. For every
- method to be used a function is generated by script to qualify
- arguments and automatically reference the method description for
- a lookup. The generated function looks up the method by using
- the unique id associated with the method description as a hash
- into the cache associated with the object's class. If the method
- is not cached the generated function proceeds to use the class'
- table to find the method. If the method is found then the
- associated function within the class is used; otherwise, the
- default function associated with the method description is
- used.</para>
-
- <para>These indirections can be visualized as the
- following:</para>
-
- <programlisting>object-&gt;cache&lt;-&gt;class</programlisting>
-
- </sect1>
-
- <sect1 xml:id="kernel-objects-using">
- <title>Using Kobj</title>
-
- <sect2>
- <title>Structures</title>
-
- <programlisting>struct kobj_method</programlisting>
- </sect2>
-
- <sect2>
- <title>Functions</title>
-
- <programlisting>void kobj_class_compile(kobj_class_t cls);
-void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);
-void kobj_class_free(kobj_class_t cls);
-kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags);
-void kobj_init(kobj_t obj, kobj_class_t cls);
-void kobj_delete(kobj_t obj, struct malloc_type *mtype);</programlisting>
- </sect2>
-
- <sect2>
- <title>Macros</title>
-
- <programlisting>KOBJ_CLASS_FIELDS
-KOBJ_FIELDS
-DEFINE_CLASS(name, methods, size)
-KOBJMETHOD(NAME, FUNC)</programlisting>
- </sect2>
-
- <sect2>
- <title>Headers</title>
-
- <programlisting>&lt;sys/param.h&gt;
-&lt;sys/kobj.h&gt;</programlisting>
- </sect2>
-
- <sect2>
- <title>Creating an Interface Template</title>
-
- <indexterm><primary>Kernel Objects</primary>
- <secondary>interface</secondary></indexterm>
-
- <para>The first step in using Kobj is to create an
- Interface. Creating the interface involves creating a template
- that the script
- <filename>src/sys/kern/makeobjops.pl</filename> can use to
- generate the header and code for the method declarations and
- method lookup functions.</para>
-
- <para>Within this template the following keywords are used:
- <literal>#include</literal>, <literal>INTERFACE</literal>,
- <literal>CODE</literal>, <literal>METHOD</literal>,
- <literal>STATICMETHOD</literal>, and
- <literal>DEFAULT</literal>.</para>
-
- <para>The <literal>#include</literal> statement and what follows
- it is copied verbatim to the head of the generated code
- file.</para>
-
- <para>For example:</para>
-
- <programlisting>#include &lt;sys/foo.h&gt;</programlisting>
-
- <para>The <literal>INTERFACE</literal> keyword is used to define
- the interface name. This name is concatenated with each method
- name as [interface name]_[method name]. Its syntax is
- INTERFACE [interface name];.</para>
-
- <para>For example:</para>
-
- <programlisting>INTERFACE foo;</programlisting>
-
- <para>The <literal>CODE</literal> keyword copies its arguments
- verbatim into the code file. Its syntax is
- <literal>CODE { [whatever] };</literal></para>
-
- <para>For example:</para>
-
- <programlisting>CODE {
- struct foo * foo_alloc_null(struct bar *)
- {
- return NULL;
-}
-};</programlisting>
-
- <para>The <literal>METHOD</literal> keyword describes a method. Its syntax is
- <literal>METHOD [return type] [method name] { [object [,
- arguments]] };</literal></para>
-
- <para>For example:</para>
-
- <programlisting>METHOD int bar {
- struct object *;
- struct foo *;
- struct bar;
-};</programlisting>
-
- <para>The <literal>DEFAULT</literal> keyword may follow the
- <literal>METHOD</literal> keyword. It extends the
- <literal>METHOD</literal> key word to include the default
- function for method. The extended syntax is
- <literal>METHOD [return type] [method name] {
- [object; [other arguments]] }DEFAULT [default
- function];</literal></para>
-
- <para>For example:</para>
-
- <programlisting>METHOD int bar {
- struct object *;
- struct foo *;
- int bar;
-} DEFAULT foo_hack;</programlisting>
-
- <para>The <literal>STATICMETHOD</literal> keyword is used like
- the <literal>METHOD</literal> keyword except the kobj data is not
- at the head of the object structure so casting to kobj_t would
- be incorrect. Instead <literal>STATICMETHOD</literal> relies on the Kobj data being
- referenced as 'ops'. This is also useful for calling
- methods directly out of a class's method table.</para>
-
- <para>Other complete examples:</para>
-
- <programlisting>src/sys/kern/bus_if.m
-src/sys/kern/device_if.m</programlisting>
-
- </sect2>
-
- <sect2>
- <title>Creating a Class</title>
-
- <indexterm><primary>Kernel Objects</primary>
- <secondary>class</secondary></indexterm>
-
- <para>The second step in using Kobj is to create a class. A
- class consists of a name, a table of methods, and the size of
- objects if Kobj's object handling facilities are used. To
- create the class use the macro
- <function>DEFINE_CLASS()</function>. To create the method
- table create an array of kobj_method_t terminated by a NULL
- entry. Each non-NULL entry may be created using the macro
- <function>KOBJMETHOD()</function>.</para>
-
- <para>For example:</para>
-
- <programlisting>DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));
-
-kobj_method_t foomethods[] = {
- KOBJMETHOD(bar_doo, foo_doo),
- KOBJMETHOD(bar_foo, foo_foo),
- { NULL, NULL}
-};</programlisting>
-
- <para>The class must be <quote>compiled</quote>. Depending on
- the state of the system at the time that the class is to be
- initialized a statically allocated cache, <quote>ops
- table</quote> have to be used. This can be accomplished by
- declaring a <varname remap="structname">struct kobj_ops</varname> and using
- <function>kobj_class_compile_static();</function> otherwise,
- <function>kobj_class_compile()</function> should be used.</para>
- </sect2>
-
- <sect2>
- <title>Creating an Object</title>
-
- <indexterm><primary>Kernel Objects</primary>
- <secondary>object</secondary></indexterm>
-
- <para>The third step in using Kobj involves how to define the
- object. Kobj object creation routines assume that Kobj data is
- at the head of an object. If this in not appropriate you will
- have to allocate the object yourself and then use
- <function>kobj_init()</function> on the Kobj portion of it;
- otherwise, you may use <function>kobj_create()</function> to
- allocate and initialize the Kobj portion of the object
- automatically. <function>kobj_init()</function> may also be
- used to change the class that an object uses.</para>
-
- <para>To integrate Kobj into the object you should use the macro
- KOBJ_FIELDS.</para>
-
- <para>For example</para>
-
- <programlisting>struct foo_data {
- KOBJ_FIELDS;
- foo_foo;
- foo_bar;
-};</programlisting>
- </sect2>
-
- <sect2>
- <title>Calling Methods</title>
-
- <para>The last step in using Kobj is to simply use the generated
- functions to use the desired method within the object's
- class. This is as simple as using the interface name and the
- method name with a few modifications. The interface name
- should be concatenated with the method name using a '_'
- between them, all in upper case.</para>
-
- <para>For example, if the interface name was foo and the method
- was bar then the call would be:</para>
-
- <programlisting>[return value = ] FOO_BAR(object [, other parameters]);</programlisting>
-
- </sect2>
-
- <sect2>
- <title>Cleaning Up</title>
-
- <para>When an object allocated through
- <function>kobj_create()</function> is no longer needed
- <function>kobj_delete()</function> may be called on it, and
- when a class is no longer being used
- <function>kobj_class_free()</function> may be called on it.</para>
- </sect2>
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/locking/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/locking/chapter.xml
deleted file mode 100644
index e45f45ecf8..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/locking/chapter.xml
+++ /dev/null
@@ -1,391 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- The FreeBSD Documentation Project
- The FreeBSD SMP Next Generation Project
-
- $FreeBSD$
--->
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:id="locking">
- <title>Locking Notes</title>
-
- <indexterm>
- <primary>SMP Next Generation Project</primary>
- </indexterm>
-
- <para><emphasis>This chapter is maintained by the FreeBSD SMP Next
- Generation Project.</emphasis></para>
-
- <indexterm><primary>locking</primary></indexterm>
- <indexterm><primary>multi-processing</primary></indexterm>
- <indexterm><primary>mutexes</primary></indexterm>
- <indexterm><primary>lockmgr</primary></indexterm>
- <indexterm><primary>atomic operations</primary></indexterm>
- <para>This document outlines the locking used in the FreeBSD kernel
- to permit effective multi-processing within the kernel. Locking
- can be achieved via several means. Data structures can be
- protected by mutexes or &man.lockmgr.9; locks. A few variables
- are protected simply by always using atomic operations to access
- them.</para>
-
- <sect1 xml:id="locking-mutexes">
- <title>Mutexes</title>
-
- <para>A mutex is simply a lock used to guarantee mutual exclusion.
- Specifically, a mutex may only be owned by one entity at a time.
- If another entity wishes to obtain a mutex that is already
- owned, it must wait until the mutex is released. In the FreeBSD
- kernel, mutexes are owned by processes.</para>
-
- <para>Mutexes may be recursively acquired, but they are intended
- to be held for a short period of time. Specifically, one may
- not sleep while holding a mutex. If you need to hold a lock
- across a sleep, use a &man.lockmgr.9; lock.</para>
-
- <para>Each mutex has several properties of interest:</para>
-
- <variablelist>
- <varlistentry>
- <term>Variable Name</term>
- <listitem>
- <para>The name of the <type>struct mtx</type> variable in
- the kernel source.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Logical Name</term>
- <listitem>
- <para>The name of the mutex assigned to it by
- <function>mtx_init</function>. This name is displayed in
- KTR trace messages and witness errors and warnings and is
- used to distinguish mutexes in the witness code.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Type</term>
- <listitem>
- <para>The type of the mutex in terms of the
- <constant>MTX_*</constant> flags. The meaning for each
- flag is related to its meaning as documented in
- &man.mutex.9;.</para>
-
- <variablelist>
- <varlistentry>
- <term><constant>MTX_DEF</constant></term>
- <listitem>
- <para>A sleep mutex</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>MTX_SPIN</constant></term>
- <listitem>
- <para>A spin mutex</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>MTX_RECURSE</constant></term>
- <listitem>
- <para>This mutex is allowed to recurse.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Protectees</term>
- <listitem>
- <para>A list of data structures or data structure members
- that this entry protects. For data structure members, the
- name will be in the form of <varname
- remap="structname">structure name</varname>.<varname
- remap="structfield">member name</varname>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Dependent Functions</term>
- <listitem>
- <para>Functions that can only be called if this mutex is
- held.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <table frame="all" colsep="1" rowsep="1" pgwide="1">
- <title>Mutex List</title>
-
- <indexterm>
- <primary>locks</primary>
- <secondary>sched_lock</secondary>
- </indexterm>
-
- <indexterm>
- <primary>locks</primary>
- <secondary>vm86pcb_lock</secondary>
- </indexterm>
-
- <indexterm>
- <primary>locks</primary>
- <secondary>Giant</secondary>
- </indexterm>
-
- <indexterm>
- <primary>locks</primary>
- <secondary>callout_lock</secondary>
- </indexterm>
-
- <tgroup cols="5">
- <thead>
- <row>
- <entry>Variable Name</entry>
- <entry>Logical Name</entry>
- <entry>Type</entry>
- <entry>Protectees</entry>
- <entry>Dependent Functions</entry>
- </row>
- </thead>
-
- <!-- The scheduler lock -->
- <tbody>
- <row>
- <entry>sched_lock</entry>
- <entry>
- <quote>sched lock</quote></entry>
- <entry>
- <constant>MTX_SPIN</constant> |
- <constant>MTX_RECURSE</constant></entry>
- <entry>
- <varname>_gmonparam</varname>,
- <varname>cnt.v_swtch</varname>,
- <varname>cp_time</varname>,
- <varname>curpriority</varname>,
- <varname remap="structname">mtx</varname>.<varname
- remap="structfield">mtx_blocked</varname>,
- <varname remap="structname">mtx</varname>.<varname
- remap="structfield">mtx_contested</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_procq</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_slpq</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_sflag</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_stat</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_estcpu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_cpticks</varname>
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_pctcpu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_wchan</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_wmesg</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_swtime</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_slptime</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_runtime</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_uu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_su</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_iu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_uticks</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_sticks</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_iticks</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_oncpu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_lastcpu</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_rqindex</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_heldmtx</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_blocked</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_mtxname</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_contested</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_priority</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_usrpri</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_nativepri</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_nice</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_rtprio</varname>,
- <varname>pscnt</varname>,
- <varname>slpque</varname>,
- <varname>itqueuebits</varname>,
- <varname>itqueues</varname>,
- <varname>rtqueuebits</varname>,
- <varname>rtqueues</varname>,
- <varname>queuebits</varname>,
- <varname>queues</varname>,
- <varname>idqueuebits</varname>,
- <varname>idqueues</varname>,
- <varname>switchtime</varname>,
- <varname>switchticks</varname></entry>
- <entry>
- <function>setrunqueue</function>,
- <function>remrunqueue</function>,
- <function>mi_switch</function>,
- <function>chooseproc</function>,
- <function>schedclock</function>,
- <function>resetpriority</function>,
- <function>updatepri</function>,
- <function>maybe_resched</function>,
- <function>cpu_switch</function>,
- <function>cpu_throw</function>,
- <function>need_resched</function>,
- <function>resched_wanted</function>,
- <function>clear_resched</function>,
- <function>aston</function>,
- <function>astoff</function>,
- <function>astpending</function>,
- <function>calcru</function>,
- <function>proc_compare</function></entry>
- </row>
-
- <!-- The vm86 pcb lock -->
- <row>
- <entry>vm86pcb_lock</entry>
- <entry><quote>vm86pcb lock</quote></entry>
- <entry>
- <constant>MTX_DEF</constant></entry>
- <entry>
- <varname>vm86pcb</varname></entry>
- <entry>
- <function>vm86_bioscall</function></entry>
- </row>
-
- <!-- Giant -->
- <row>
- <entry>Giant</entry>
- <entry><quote>Giant</quote></entry>
- <entry>
- <constant>MTX_DEF</constant> |
- <constant>MTX_RECURSE</constant></entry>
- <entry>nearly everything</entry>
- <entry>lots</entry>
- </row>
-
- <!-- The callout lock -->
- <row>
- <entry>callout_lock</entry>
- <entry><quote>callout lock</quote></entry>
- <entry>
- <constant>MTX_SPIN</constant> |
- <constant>MTX_RECURSE</constant></entry>
- <entry>
- <varname>callfree</varname>,
- <varname>callwheel</varname>,
- <varname>nextsoftcheck</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_itcallout</varname>,
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_slpcallout</varname>,
- <varname>softticks</varname>,
- <varname>ticks</varname></entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect1>
-
- <sect1 xml:id="locking-sx">
- <title>Shared Exclusive Locks</title>
-
- <para>These locks provide basic reader-writer type functionality
- and may be held by a sleeping process. Currently they are
- backed by &man.lockmgr.9;.</para>
- <indexterm>
- <primary>locks</primary>
- <secondary>shared exclusive</secondary>
- </indexterm>
-
- <table>
- <title>Shared Exclusive Lock List</title>
-
- <indexterm>
- <primary>locks</primary>
- <secondary>allproc_lock</secondary>
- </indexterm>
- <indexterm>
- <primary>locks</primary>
- <secondary>proctree_lock</secondary>
- </indexterm>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Variable Name</entry>
- <entry>Protectees</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><varname>allproc_lock</varname></entry>
- <entry>
- <varname>allproc</varname>
- <varname>zombproc</varname>
- <varname>pidhashtbl</varname>
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_list</varname>
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_hash</varname>
- <varname>nextpid</varname></entry>
- </row>
-
- <row>
- <entry><varname>proctree_lock</varname></entry>
- <entry>
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_children</varname>
- <varname remap="structname">proc</varname>.<varname
- remap="structfield">p_sibling</varname></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect1>
-
- <sect1 xml:id="locking-atomic">
- <title>Atomically Protected Variables</title>
-
- <indexterm>
- <primary>atomically protected variables</primary>
- </indexterm>
-
- <para>An atomically protected variable is a special variable that
- is not protected by an explicit lock. Instead, all data
- accesses to the variables use special atomic operations as
- described in &man.atomic.9;. Very few variables are treated
- this way, although other synchronization primitives such as
- mutexes are implemented with atomically protected
- variables.</para>
-
- <itemizedlist>
- <listitem>
- <para><varname remap="structname">mtx</varname>.<varname
- remap="structfield">mtx_lock</varname></para>
- </listitem>
- </itemizedlist>
- </sect1>
-</chapter>
diff --git a/en_US.ISO8859-1/books/arch-handbook/mac.ent b/en_US.ISO8859-1/books/arch-handbook/mac.ent
deleted file mode 100644
index 76a5938a76..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/mac.ent
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- $FreeBSD$ -->
-
-<!ENTITY mac.mpo "mpo">
-<!ENTITY mac.thead '
- <colspec xmlns="http://docbook.org/ns/docbook" colname="first" colwidth="0"/>
- <colspec xmlns="http://docbook.org/ns/docbook" colwidth="0"/>
- <colspec xmlns="http://docbook.org/ns/docbook" colname="last" colwidth="0"/>
-
- <thead xmlns="http://docbook.org/ns/docbook">
- <row>
- <entry>Parameter</entry>
- <entry>Description</entry>
- <entry>Locking</entry>
- </row>
- </thead>
-'>
-
-<!ENTITY mac.externalize.paramdefs '
- <paramdef xmlns="http://docbook.org/ns/docbook">struct label *<parameter>label</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">char *<parameter>element_name</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">struct sbuf *<parameter>sb</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">int <parameter>*claimed</parameter></paramdef>
-'>
-
-<!ENTITY mac.externalize.tbody '
- <tbody xmlns="http://docbook.org/ns/docbook">
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label to be externalized</entry>
- </row>
-
- <row>
- <entry><parameter>element_name</parameter></entry>
- <entry>Name of the policy whose label should be externalized</entry>
- </row>
-
- <row>
- <entry><parameter>sb</parameter></entry>
- <entry>String buffer to be filled with a text representation of
- label</entry>
- </row>
-
- <row>
- <entry><parameter>claimed</parameter></entry>
- <entry>Should be incremented when <parameter>element_data</parameter>
- can be filled in.</entry>
- </row>
- </tbody>
-'>
-
-<!ENTITY mac.externalize.para '
- <para xmlns="http://docbook.org/ns/docbook">Produce an externalized label based on the label structure passed.
- An externalized label consists of a text representation of the label
- contents that can be used with userland applications and read by the
- user. Currently, all policies&apos; <function>externalize</function> entry
- points will be called, so the implementation should check the contents
- of <parameter>element_name</parameter> before attempting to fill in
- <parameter>sb</parameter>. If
- <parameter>element_name</parameter> does not match the name of your
- policy, simply return <returnvalue>0</returnvalue>. Only return nonzero
- if an error occurs while externalizing the label data. Once the policy
- fills in <parameter>element_data</parameter>, <varname>*claimed</varname>
- should be incremented.</para>
-'>
-
-<!ENTITY mac.internalize.paramdefs '
- <paramdef xmlns="http://docbook.org/ns/docbook">struct label *<parameter>label</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">char *<parameter>element_name</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">char *<parameter>element_data</parameter></paramdef>
- <paramdef xmlns="http://docbook.org/ns/docbook">int *<parameter>claimed</parameter></paramdef>
-'>
-
-<!ENTITY mac.internalize.tbody '
- <tbody xmlns="http://docbook.org/ns/docbook">
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label to be filled in</entry>
- </row>
-
- <row>
- <entry><parameter>element_name</parameter></entry>
- <entry>Name of the policy whose label should be internalized</entry>
- </row>
-
- <row>
- <entry><parameter>element_data</parameter></entry>
- <entry>Text data to be internalized</entry>
- </row>
-
- <row>
- <entry><parameter>claimed</parameter></entry>
- <entry>Should be incremented when data can be successfully
- internalized.</entry>
- </row>
- </tbody>
-'>
-
-<!ENTITY mac.internalize.para '
- <para xmlns="http://docbook.org/ns/docbook">Produce an internal label structure based on externalized label data
- in text format. Currently, all policies&apos; <function>internalize</function>
- entry points are called when internalization is requested, so the
- implementation should compare the contents of
- <parameter>element_name</parameter> to its own name in order to be sure
- it should be internalizing the data in <parameter>element_data</parameter>.
- Just as in the <function>externalize</function> entry points, the entry
- point should return <returnvalue>0</returnvalue> if
- <parameter>element_name</parameter> does not match its own name, or when
- data can successfully be internalized, in which case
- <varname>*claimed</varname> should be incremented.</para>
-'>
diff --git a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.xml b/en_US.ISO8859-1/books/arch-handbook/mac/chapter.xml
deleted file mode 100644
index 9f1c6beb44..0000000000
--- a/en_US.ISO8859-1/books/arch-handbook/mac/chapter.xml
+++ /dev/null
@@ -1,8068 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!--
- Copyright (c) 2002-2005 Networks Associates Technology, Inc.
- All rights reserved.
-
- This software was developed for the FreeBSD Project by
- Chris Costello at Safeport Network Services and Network Associates Labs,
- the Security Research Division of Network Associates, Inc. under
- DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
- DARPA CHATS research program.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
- $FreeBSD$
--->
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
- xml:id="mac">
- <info>
- <title>The TrustedBSD MAC Framework</title>
-
- <authorgroup>
- <author>
- <personname>
- <firstname>Chris</firstname>
- <surname>Costello</surname>
- </personname>
- <affiliation>
- <orgname>TrustedBSD Project</orgname>
- <address>
- <email>chris@FreeBSD.org</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <personname>
- <firstname>Robert</firstname>
- <surname>Watson</surname>
- </personname>
- <affiliation>
- <orgname>TrustedBSD Project</orgname>
- <address>
- <email>rwatson@FreeBSD.org</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
- </info>
-
- <sect1 xml:id="mac-copyright">
- <title>MAC Documentation Copyright</title>
-
- <para>This documentation was developed for the FreeBSD Project by
- Chris Costello at Safeport Network Services and Network
- Associates Laboratories, the Security Research Division of
- Network Associates, Inc. under DARPA/SPAWAR contract
- N66001-01-C-8035 (<quote>CBOSS</quote>), as part of the DARPA
- CHATS research program.</para>
-
- <para>Redistribution and use in source (SGML DocBook) and
- 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth)
- with or without modification, are permitted provided that the
- following conditions are met:</para>
-
- <orderedlist>
- <listitem>
- <para>Redistributions of source code (SGML DocBook) must
- retain the above copyright notice, this list of conditions
- and the following disclaimer as the first lines of this file
- unmodified.</para>
- </listitem>
-
- <listitem>
- <para>Redistributions in compiled form (transformed to other
- DTDs, converted to PDF, PostScript, RTF and other formats)
- must reproduce the above copyright notice, this list of
- conditions and the following disclaimer in the documentation
- and/or other materials provided with the
- distribution.</para>
- </listitem>
- </orderedlist>
-
- <important>
- <para>THIS DOCUMENTATION IS PROVIDED BY THE NETWORKS ASSOCIATES
- TECHNOLOGY, INC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL NETWORKS ASSOCIATES TECHNOLOGY,
- INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN
- IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</para>
- </important>
- </sect1>
-
- <sect1 xml:id="mac-synopsis">
- <title>Synopsis</title>
-
- <para>FreeBSD includes experimental support for several mandatory
- access control policies, as well as a framework for kernel
- security extensibility, the TrustedBSD MAC Framework. The MAC
- Framework is a pluggable access control framework, permitting
- new security policies to be easily linked into the kernel,
- loaded at boot, or loaded dynamically at run-time. The
- framework provides a variety of features to make it easier to
- implement new security policies, including the ability to easily
- tag security labels (such as confidentiality information) onto
- system objects.</para>
-
- <para>This chapter introduces the MAC policy framework and
- provides documentation for a sample MAC policy module.</para>
- </sect1>
-
-
- <sect1 xml:id="mac-introduction">
- <title>Introduction</title>
-
- <para>The TrustedBSD MAC framework provides a mechanism to allow
- the compile-time or run-time extension of the kernel access
- control model. New system policies may be implemented as kernel
- modules and linked to the kernel; if multiple policy modules are
- present, their results will be composed. The MAC Framework
- provides a variety of access control infrastructure services to
- assist policy writers, including support for transient and
- persistent policy-agnostic object security labels. This support
- is currently considered experimental.</para>
-
- <para>This chapter provides information appropriate for developers
- of policy modules, as well as potential consumers of MAC-enabled
- environments, to learn about how the MAC Framework supports
- access control extension of the kernel.</para>
- </sect1>
-
- <sect1 xml:id="mac-background">
- <title>Policy Background</title>
-
- <para>Mandatory Access Control (MAC), refers to a set of access
- control policies that are mandatorily enforced on users by the
- operating system. MAC policies may be contrasted with
- Discretionary Access Control (DAC) protections, by which
- non-administrative users may (at their discretion) protect
- objects. In traditional UNIX systems, DAC protections include
- file permissions and access control lists; MAC protections
- include process controls preventing inter-user debugging and
- firewalls. A variety of MAC policies have been formulated by
- operating system designers and security researches, including
- the Multi-Level Security (MLS) confidentiality policy, the Biba
- integrity policy, Role-Based Access Control (RBAC), Domain and
- Type Enforcement (DTE), and Type Enforcement (TE). Each model
- bases decisions on a variety of factors, including user
- identity, role, and security clearance, as well as security
- labels on objects representing concepts such as data sensitivity
- and integrity.</para>
-
- <para>The TrustedBSD MAC Framework is capable of supporting policy
- modules that implement all of these policies, as well as a broad
- class of system hardening policies, which may use existing
- security attributes, such as user and group IDs, as well as
- extended attributes on files, and other system properties. In
- addition, despite the name, the MAC Framework can also be used
- to implement purely discretionary policies, as policy modules
- are given substantial flexibility in how they authorize
- protections.</para>
- </sect1>
-
- <sect1 xml:id="mac-framework-kernel-arch">
- <title>MAC Framework Kernel Architecture</title>
-
- <para>The TrustedBSD MAC Framework permits kernel modules to
- extend the operating system security policy, as well as
- providing infrastructure functionality required by many access
- control modules. If multiple policies are simultaneously
- loaded, the MAC Framework will usefully (for some definition of
- useful) compose the results of the policies.</para>
-
- <sect2 xml:id="mac-framework-kernel-arch-elements">
- <title>Kernel Elements</title>
-
- <para>The MAC Framework contains a number of kernel
- elements:</para>
-
- <itemizedlist>
- <listitem>
- <para>Framework management interfaces</para>
- </listitem>
- <listitem>
- <para>Concurrency and synchronization primitives.</para>
- </listitem>
- <listitem>
- <para>Policy registration</para>
- </listitem>
- <listitem>
- <para>Extensible security label for kernel objects</para>
- </listitem>
- <listitem>
- <para>Policy entry point composition operators</para>
- </listitem>
- <listitem>
- <para>Label management primitives</para>
- </listitem>
- <listitem>
- <para>Entry point API invoked by kernel services</para>
- </listitem>
- <listitem>
- <para>Entry point API to policy modules</para>
- </listitem>
- <listitem>
- <para>Entry points implementations (policy life cycle,
- object life cycle/label management, access control
- checks).</para>
- </listitem>
- <listitem>
- <para>Policy-agnostic label-management system calls</para>
- </listitem>
- <listitem>
- <para><function>mac_syscall()</function> multiplex system
- call</para>
- </listitem>
- <listitem>
- <para>Various security policies implemented as MAC policy
- modules</para>
- </listitem>
- </itemizedlist>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-management">
- <title>Framework Management Interfaces</title>
-
- <para>The TrustedBSD MAC Framework may be directly managed using
- sysctl's, loader tunables, and system calls.</para>
-
- <para>In most cases, sysctl's and loader tunables of the same
- name modify the same parameters, and control behavior such as
- enforcement of protections relating to various kernel
- subsystems. In addition, if MAC debugging support is compiled
- into the kernel, several counters will be maintained tracking
- label allocation. It is generally advisable that
- per-subsystem enforcement controls not be used to control
- policy behavior in production environments, as they broadly
- impact the operation of all active policies. Instead,
- per-policy controls should be preferred, as they provide
- greater granularity and greater operational consistency for
- policy modules.</para>
-
- <para>Loading and unloading of policy modules is performed using
- the system module management system calls and other system
- interfaces, including boot loader variables; policy modules
- will have the opportunity to influence load and unload events,
- including preventing undesired unloading of the policy.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-synchronization">
- <title>Policy List Concurrency and Synchronization</title>
-
- <para>As the set of active policies may change at run-time, and
- the invocation of entry points is non-atomic, synchronization
- is required to prevent loading or unloading of policies while
- an entry point invocation is in progress, freezing the set of
- active policies for the duration. This is accomplished by
- means of a framework busy count: whenever an entry point is
- entered, the busy count is incremented; whenever it is exited,
- the busy count is decremented. While the busy count is
- elevated, policy list changes are not permitted, and threads
- attempting to modify the policy list will sleep until the list
- is not busy. The busy count is protected by a mutex, and a
- condition variable is used to wake up sleepers waiting on
- policy list modifications. One side effect of this
- synchronization model is that recursion into the MAC Framework
- from within a policy module is permitted, although not
- generally used.</para>
-
- <para>Various optimizations are used to reduce the overhead of
- the busy count, including avoiding the full cost of
- incrementing and decrementing if the list is empty or contains
- only static entries (policies that are loaded before the
- system starts, and cannot be unloaded). A compile-time option
- is also provided which prevents any change in the set of
- loaded policies at run-time, which eliminates the mutex
- locking costs associated with supporting dynamically loaded
- and unloaded policies as synchronization is no longer
- required.</para>
-
- <para>As the MAC Framework is not permitted to block in some
- entry points, a normal sleep lock cannot be used; as a result,
- it is possible for the load or unload attempt to block for a
- substantial period of time waiting for the framework to become
- idle.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-label-synchronization">
- <title>Label Synchronization</title>
-
- <para>As kernel objects of interest may generally be accessed
- from more than one thread at a time, and simultaneous entry of
- more than one thread into the MAC Framework is permitted,
- security attribute storage maintained by the MAC Framework is
- carefully synchronized. In general, existing kernel
- synchronization on kernel object data is used to protect MAC
- Framework security labels on the object: for example, MAC
- labels on sockets are protected using the existing socket
- mutex. Likewise, semantics for concurrent access are
- generally identical to those of the container objects: for
- credentials, copy-on-write semantics are maintained for label
- contents as with the remainder of the credential structure.
- The MAC Framework asserts necessary locks on objects when
- invoked with an object reference. Policy authors must be
- aware of these synchronization semantics, as they will
- sometimes limit the types of accesses permitted on labels: for
- example, when a read-only reference to a credential is passed
- to a policy via an entry point, only read operations are
- permitted on the label state attached to the
- credential.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-policy-synchronization">
- <title>Policy Synchronization and Concurrency</title>
-
- <para>Policy modules must be written to assume that many kernel
- threads may simultaneously enter one more policy entry points
- due to the parallel and preemptive nature of the FreeBSD
- kernel. If the policy module makes use of mutable state, this
- may require the use of synchronization primitives within the
- policy to prevent inconsistent views on that state resulting
- in incorrect operation of the policy. Policies will generally
- be able to make use of existing FreeBSD synchronization
- primitives for this purpose, including mutexes, sleep locks,
- condition variables, and counting semaphores. However,
- policies should be written to employ these primitives
- carefully, respecting existing kernel lock orders, and
- recognizing that some entry points are not permitted to sleep,
- limiting the use of primitives in those entry points to
- mutexes and wakeup operations.</para>
-
- <para>When policy modules call out to other kernel subsystems,
- they will generally need to release any in-policy locks in
- order to avoid violating the kernel lock order or risking lock
- recursion. This will maintain policy locks as leaf locks in
- the global lock order, helping to avoid deadlock.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-registration">
- <title>Policy Registration</title>
-
- <para>The MAC Framework maintains two lists of active policies:
- a static list, and a dynamic list. The lists differ only with
- regards to their locking semantics: an elevated reference
- count is not required to make use of the static list. When
- kernel modules containing MAC Framework policies are loaded,
- the policy module will use <literal>SYSINIT</literal> to
- invoke a registration function; when a policy module is
- unloaded, <literal>SYSINIT</literal> will likewise invoke a
- de-registration function. Registration may fail if a policy
- module is loaded more than once, if insufficient resources are
- available for the registration (for example, the policy might
- require labeling and insufficient labeling state might be
- available), or other policy prerequisites might not be met
- (some policies may only be loaded prior to boot). Likewise,
- de-registration may fail if a policy is flagged as not
- unloadable.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-entrypoints">
- <title>Entry Points</title>
-
- <para>Kernel services interact with the MAC Framework in two
- ways: they invoke a series of APIs to notify the framework of
- relevant events, and they provide a policy-agnostic label
- structure pointer in security-relevant objects. The label
- pointer is maintained by the MAC Framework via label
- management entry points, and permits the Framework to offer a
- labeling service to policy modules through relatively
- non-invasive changes to the kernel subsystem maintaining the
- object. For example, label pointers have been added to
- processes, process credentials, sockets, pipes, vnodes, Mbufs,
- network interfaces, IP reassembly queues, and a variety of
- other security-relevant structures. Kernel services also
- invoke the MAC Framework when they perform important security
- decisions, permitting policy modules to augment those
- decisions based on their own criteria (possibly including data
- stored in security labels). Most of these security critical
- decisions will be explicit access control checks; however,
- some affect more general decision functions such as packet
- matching for sockets and label transition at program
- execution.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-composition">
- <title>Policy Composition</title>
-
- <para>When more than one policy module is loaded into the kernel
- at a time, the results of the policy modules will be composed
- by the framework using a composition operator. This operator
- is currently hard-coded, and requires that all active policies
- must approve a request for it to return success. As policies
- may return a variety of error conditions (success, access
- denied, object does not exist, ...), a precedence operator
- selects the resulting error from the set of errors returned by
- policies. In general, errors indicating that an object does
- not exist will be preferred to errors indicating that access
- to an object is denied. While it is not guaranteed that the
- resulting composition will be useful or secure, we have found
- that it is for many useful selections of policies. For
- example, traditional trusted systems often ship with two or
- more policies using a similar composition.</para>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-labels">
- <title>Labeling Support</title>
-
- <para>As many interesting access control extensions rely on
- security labels on objects, the MAC Framework provides a set
- of policy-agnostic label management system calls covering a
- variety of user-exposed objects. Common label types include
- partition identifiers, sensitivity labels, integrity labels,
- compartments, domains, roles, and types. By policy agnostic,
- we mean that policy modules are able to completely define the
- semantics of meta-data associated with an object. Policy
- modules participate in the internalization and externalization
- of string-based labels provides by user applications, and can
- expose multiple label elements to applications if
- desired.</para>
-
- <para>In-memory labels are stored in slab-allocated <varname
- remap="structname">struct label</varname>, which consists of
- a fixed-length array of unions, each holding a <literal>void
- *</literal> pointer and a <literal>long</literal>. Policies
- registering for label storage will be assigned a "slot"
- identifier, which may be used to dereference the label
- storage. The semantics of the storage are left entirely up to
- the policy module: modules are provided with a variety of
- entry points associated with the kernel object life cycle,
- including initialization, association/creation, and
- destruction. Using these interfaces, it is possible to
- implement reference counting and other storage models. Direct
- access to the object structure is generally not required by
- policy modules to retrieve a label, as the MAC Framework
- generally passes both a pointer to the object and a direct
- pointer to the object's label into entry points. The primary
- exception to this rule is the process credential, which must
- be manually dereferenced to access the credential label. This
- may change in future revisions of the MAC Framework.</para>
-
- <para>Initialization entry points frequently include a sleeping
- disposition flag indicating whether or not an initialization
- is permitted to sleep; if sleeping is not permitted, a failure
- may be returned to cancel allocation of the label (and hence
- object). This may occur, for example, in the network stack
- during interrupt handling, where sleeping is not permitted, or
- while the caller holds a mutex. Due to the performance cost
- of maintaining labels on in-flight network packets (Mbufs),
- policies must specifically declare a requirement that Mbuf
- labels be allocated. Dynamically loaded policies making use
- of labels must be able to handle the case where their init
- function has not been called on an object, as objects may
- already exist when the policy is loaded. The MAC Framework
- guarantees that uninitialized label slots will hold a 0 or
- NULL value, which policies may use to detect uninitialized
- values. However, as allocation of Mbuf labels is conditional,
- policies must also be able to handle a NULL label pointer for
- Mbufs if they have been loaded dynamically.</para>
-
- <para>In the case of file system labels, special support is
- provided for the persistent storage of security labels in
- extended attributes. Where available, extended attribute
- transactions are used to permit consistent compound updates of
- security labels on vnodes--currently this support is present
- only in the UFS2 file system. Policy authors may choose to
- implement multilabel file system object labels using one (or
- more) extended attributes. For efficiency reasons, the vnode
- label (<literal>v_label</literal>) is a cache of any on-disk
- label; policies are able to load values into the cache when
- the vnode is instantiated, and update the cache as needed. As
- a result, the extended attribute need not be directly accessed
- with every access control check.</para>
-
- <note>
- <para>Currently, if a labeled policy permits dynamic
- unloading, its state slot cannot be reclaimed, which places
- a strict (and relatively low) bound on the number of
- unload-reload operations for labeled policies.</para>
- </note>
- </sect2>
-
- <sect2 xml:id="mac-framework-kernel-arch-syscalls">
- <title>System Calls</title>
-
- <para>The MAC Framework implements a number of system calls:
- most of these calls support the policy-agnostic label
- retrieval and manipulation APIs exposed to user
- applications.</para>
-
- <para>The label management calls accept a label description
- structure, <varname remap="structname">struct mac</varname>,
- which contains a series of MAC label elements. Each element
- contains a character string name, and character string value.
- Each policy will be given the chance to claim a particular
- element name, permitting policies to expose multiple
- independent elements if desired. Policy modules perform the
- internalization and externalization between kernel labels and
- user-provided labels via entry points, permitting a variety of
- semantics. Label management system calls are generally
- wrapped by user library functions to perform memory allocation
- and error handling, simplifying user applications that must
- manage labels.</para>
-
- <para>The following MAC-related system calls are present in the
- FreeBSD kernel:</para>
-
- <itemizedlist>
- <listitem>
- <para><function>mac_get_proc()</function> may be used to
- retrieve the label of the current process.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_set_proc()</function> may be used to
- request a change in the label of the current
- process.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_get_fd()</function> may be used to
- retrieve the label of an object (file, socket, pipe, ...)
- referenced by a file descriptor.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_get_file()</function> may be used to
- retrieve the label of an object referenced by a file
- system path.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_set_fd()</function> may be used to
- request a change in the label of an object (file, socket,
- pipe, ...) referenced by a file descriptor.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_set_file()</function> may be used to
- request a change in the label of an object referenced by a
- file system path.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_syscall()</function> permits policy
- modules to create new system calls without modifying the
- system call table; it accepts a target policy name,
- operation number, and opaque argument for use by the
- policy.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_get_pid()</function> may be used to
- request the label of another process by process id.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_get_link()</function> is identical to
- <function>mac_get_file()</function>, only it will not
- follow a symbolic link if it is the final entry in the
- path, so may be used to retrieve the label on a
- symlink.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_set_link()</function> is identical to
- <function>mac_set_file()</function>, only it will not
- follow a symbolic link if it is the final entry in a path,
- so may be used to manipulate the label on a
- symlink.</para>
- </listitem>
-
- <listitem>
- <para><function>mac_execve()</function> is identical to the
- <function>execve()</function> system call, only it also
- accepts a requested label to set the process label to when
- beginning execution of a new program. This change in
- label on execution is referred to as a
- "transition".</para>
- </listitem>
-
- <listitem>
- <para><function>mac_get_peer()</function>, actually
- implemented via a socket option, retrieves the label of a
- remote peer on a socket, if available.</para>
- </listitem>
- </itemizedlist>
-
- <para>In addition to these system calls, the
- <literal>SIOCSIGMAC</literal> and
- <literal>SIOCSIFMAC</literal> network interface ioctls permit
- the labels on network interfaces to be retrieved and
- set.</para>
- </sect2>
- </sect1>
-
- <sect1 xml:id="mac-policy-architecture">
- <title>MAC Policy Architecture</title>
-
- <para>Security policies are either linked directly into the
- kernel, or compiled into loadable kernel modules that may be
- loaded at boot, or dynamically using the module loading system
- calls at runtime. Policy modules interact with the system
- through a set of declared entry points, providing access to a
- stream of system events and permitting the policy to influence
- access control decisions. Each policy contains a number of
- elements:</para>
-
- <itemizedlist>
- <listitem>
- <para>Optional configuration parameters for
- policy.</para>
- </listitem>
- <listitem>
- <para>Centralized implementation of the policy logic and
- parameters.</para>
- </listitem>
- <listitem>
- <para>Optional implementation of policy life cycle events,
- such as initialization and destruction.</para>
- </listitem>
- <listitem>
- <para>Optional support for initializing, maintaining, and
- destroying labels on selected kernel
- objects.</para>
- </listitem>
- <listitem>
- <para>Optional support for user process inspection and
- modification of labels on selected
- objects.</para>
- </listitem>
- <listitem>
- <para>Implementation of selected access control entry points
- that are of interest to the policy.</para>
- </listitem>
- <listitem>
- <para>Declaration of policy identity, module entry points, and
- policy properties.</para>
- </listitem>
- </itemizedlist>
-
- <sect2 xml:id="mac-policy-declaration">
- <title>Policy Declaration</title>
-
- <para>Modules may be declared using the
- <function>MAC_POLICY_SET()</function> macro, which names the
- policy, provides a reference to the MAC entry point vector,
- provides load-time flags determining how the policy framework
- should handle the policy, and optionally requests the
- allocation of label state by the framework.</para>
-
- <programlisting>static struct mac_policy_ops mac_<replaceable>policy</replaceable>_ops =
-{
- .mpo_destroy = mac_<replaceable>policy</replaceable>_destroy,
- .mpo_init = mac_<replaceable>policy</replaceable>_init,
- .mpo_init_bpfdesc_label = mac_<replaceable>policy</replaceable>_init_bpfdesc_label,
- .mpo_init_cred_label = mac_<replaceable>policy</replaceable>_init_label,
-/* ... */
- .mpo_check_vnode_setutimes = mac_<replaceable>policy</replaceable>_check_vnode_setutimes,
- .mpo_check_vnode_stat = mac_<replaceable>policy</replaceable>_check_vnode_stat,
- .mpo_check_vnode_write = mac_<replaceable>policy</replaceable>_check_vnode_write,
-};</programlisting>
-
- <para>The MAC policy entry point vector,
- <varname>mac_<replaceable>policy</replaceable>_ops</varname>
- in this example, associates functions defined in the module
- with specific entry points. A complete listing of available
- entry points and their prototypes may be found in the MAC
- entry point reference section. Of specific interest during
- module registration are the <symbol>.mpo_destroy</symbol> and
- <symbol>.mpo_init</symbol> entry points.
- <symbol>.mpo_init</symbol> will be invoked once a policy is
- successfully registered with the module framework but prior to
- any other entry points becoming active. This permits the
- policy to perform any policy-specific allocation and
- initialization, such as initialization of any data or locks.
- <symbol>.mpo_destroy</symbol> will be invoked when a policy
- module is unloaded to permit releasing of any allocated memory
- and destruction of locks. Currently, these two entry points
- are invoked with the MAC policy list mutex held to prevent any
- other entry points from being invoked: this will be changed,
- but in the mean time, policies should be careful about what
- kernel primitives they invoke so as to avoid lock ordering or
- sleeping problems.</para>
-
- <para>The policy declaration's module name field exists so that
- the module may be uniquely identified for the purposes of
- module dependencies. An appropriate string should be
- selected. The full string name of the policy is displayed to
- the user via the kernel log during load and unload events, and
- also exported when providing status information to userland
- processes.</para>
- </sect2>
-
- <sect2 xml:id="mac-policy-flags">
- <title>Policy Flags</title>
-
- <para>The policy declaration flags field permits the module to
- provide the framework with information about its capabilities
- at the time the module is loaded. Currently, three flags are
- defined:</para>
-
- <variablelist>
- <varlistentry>
- <term>MPC_LOADTIME_FLAG_UNLOADOK</term>
-
- <listitem>
- <para>This flag indicates that the policy module may be
- unloaded. If this flag is not provided, then the policy
- framework will reject requests to unload the module.
- This flag might be used by modules that allocate label
- state and are unable to free that state at
- runtime.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>MPC_LOADTIME_FLAG_NOTLATE</term>
-
- <listitem>
- <para>This flag indicates that the policy module must be
- loaded and initialized early in the boot process. If
- the flag is specified, attempts to register the module
- following boot will be rejected. The flag may be used
- by policies that require pervasive labeling of all
- system objects, and cannot handle objects that have not
- been properly initialized by the policy.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>MPC_LOADTIME_FLAG_LABELMBUFS</term>
-
- <listitem>
- <para>This flag indicates that the policy module requires
- labeling of Mbufs, and that memory should always be
- allocated for the storage of Mbuf labels. By default,
- the MAC Framework will not allocate label storage for
- Mbufs unless at least one loaded policy has this flag
- set. This measurably improves network performance when
- policies do not require Mbuf labeling. A kernel option,
- <literal>MAC_ALWAYS_LABEL_MBUF</literal>, exists to
- force the MAC Framework to allocate Mbuf label storage
- regardless of the setting of this flag, and may be
- useful in some environments.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <note>
- <para>Policies using the
- <literal>MPC_LOADTIME_FLAG_LABELMBUFS</literal> without the
- <literal>MPC_LOADTIME_FLAG_NOTLATE</literal> flag set must
- be able to correctly handle <literal>NULL</literal> Mbuf
- label pointers passed into entry points. This is necessary
- as in-flight Mbufs without label storage may persist after a
- policy enabling Mbuf labeling has been loaded. If a policy
- is loaded before the network subsystem is active (i.e., the
- policy is not being loaded late), then all Mbufs are
- guaranteed to have label storage.</para>
- </note>
- </sect2>
-
- <sect2 xml:id="mac-policy-entry-points">
- <title>Policy Entry Points</title>
-
- <para>Four classes of entry points are offered to policies
- registered with the framework: entry points associated with
- the registration and management of policies, entry points
- denoting initialization, creation, destruction, and other life
- cycle events for kernel objects, events associated with access
- control decisions that the policy module may influence, and
- calls associated with the management of labels on objects. In
- addition, a <function>mac_syscall()</function> entry point is
- provided so that policies may extend the kernel interface
- without registering new system calls.</para>
-
- <para>Policy module writers should be aware of the kernel
- locking strategy, as well as what object locks are available
- during which entry points. Writers should attempt to avoid
- deadlock scenarios by avoiding grabbing non-leaf locks inside
- of entry points, and also follow the locking protocol for
- object access and modification. In particular, writers should
- be aware that while necessary locks to access objects and
- their labels are generally held, sufficient locks to modify an
- object or its label may not be present for all entry points.
- Locking information for arguments is documented in the MAC
- framework entry point document.</para>
-
- <para>Policy entry points will pass a reference to the object
- label along with the object itself. This permits labeled
- policies to be unaware of the internals of the object yet
- still make decisions based on the label. The exception to
- this is the process credential, which is assumed to be
- understood by policies as a first class security object in the
- kernel.</para>
- </sect2>
- </sect1>
-
- <sect1 xml:id="mac-entry-point-reference">
- <title>MAC Policy Entry Point Reference</title>
-
- <sect2 xml:id="mac-mpo-general">
- <title>General-Purpose Module Entry Points</title>
-
- <sect3 xml:id="mac-mpo-init">
- <title><function>&mac.mpo;_init</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init</function></funcdef>
-
- <paramdef>struct mac_policy_conf
- *<parameter>conf</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>conf</parameter></entry>
- <entry>MAC policy definition</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Policy load event. The policy list mutex is held, so
- sleep operations cannot be performed, and calls out to other
- kernel subsystems must be made with caution. If potentially
- sleeping memory allocations are required during policy
- initialization, they should be made using a separate module
- SYSINIT().</para>
- </sect3>
-
- <sect3 xml:id="mpo-destroy">
- <title><function>&mac.mpo;_destroy</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy</function></funcdef>
-
- <paramdef>struct mac_policy_conf
- *<parameter>conf</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>conf</parameter></entry>
- <entry>MAC policy definition</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Policy load event. The policy list mutex is held, so
- caution should be applied.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-syscall">
- <title><function>&mac.mpo;_syscall</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_syscall</function></funcdef>
-
- <paramdef>struct thread
- *<parameter>td</parameter></paramdef>
- <paramdef>int <parameter>call</parameter></paramdef>
- <paramdef>void *<parameter>arg</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3"> &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>td</parameter></entry>
- <entry>Calling thread</entry>
- </row>
-
- <row>
- <entry><parameter>call</parameter></entry>
- <entry>Policy-specific syscall number</entry>
- </row>
-
- <row>
- <entry><parameter>arg</parameter></entry>
- <entry>Pointer to syscall arguments</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>This entry point provides a policy-multiplexed system
- call so that policies may provide additional services to
- user processes without registering specific system calls.
- The policy name provided during registration is used to
- demux calls from userland, and the arguments will be
- forwarded to this entry point. When implementing new
- services, security modules should be sure to invoke
- appropriate access control checks from the MAC framework as
- needed. For example, if a policy implements an augmented
- signal functionality, it should call the necessary signal
- access control checks to invoke the MAC framework and other
- registered policies.</para>
-
- <note>
- <para>Modules must currently perform the
- <function>copyin()</function> of the syscall data on their
- own.</para>
- </note>
- </sect3>
-
- <sect3 xml:id="mac-mpo-thread-userret">
- <title><function>&mac.mpo;_thread_userret</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_thread_userret</function></funcdef>
-
- <paramdef>struct thread
- *<parameter>td</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>td</parameter></entry>
- <entry>Returning thread</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <!-- XXX: Maybe rewrite this section. -->
- <para>This entry point permits policy modules to perform
- MAC-related events when a thread returns to user space, via
- a system call return, trap return, or otherwise. This is
- required for policies that have floating process labels, as
- it is not always possible to acquire the process lock at
- arbitrary points in the stack during system call processing;
- process labels might represent traditional authentication
- data, process history information, or other data. To employ
- this mechanism, intended changes to the process credential
- label may be stored in the <literal>p_label</literal>
- protected by a per-policy spin lock, and then set the
- per-thread <literal>TDF_ASTPENDING</literal> flag and
- per-process <literal>PS_MACPENDM</literal> flag to schedule
- a call to the userret entry point. From this entry point,
- the policy may create a replacement credential with less
- concern about the locking context. Policy writers are
- cautioned that event ordering relating to scheduling an AST
- and the AST being performed may be complex and interlaced in
- multithreaded applications.</para>
- </sect3>
- </sect2>
-
- <sect2 xml:id="mac-label-ops">
- <title>Label Operations</title>
-
- <sect3 xml:id="mac-mpo-init-bpfdesc">
- <title><function>&mac.mpo;_init_bpfdesc_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_bpfdesc_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to apply</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated bpfdesc
- (BPF descriptor). Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-cred-label">
- <title><function>&mac.mpo;_init_cred_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_cred_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to initialize</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label for a newly instantiated user
- credential. Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-devfsdirent">
- <title><function>&mac.mpo;_init_devfsdirent_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_devfsdirent_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to apply</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated devfs
- entry. Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-ifnet">
- <title><function>&mac.mpo;_init_ifnet_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_ifnet_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to apply</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated network
- interface. Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-ipq">
- <title><function>&mac.mpo;_init_ipq_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_ipq_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>flag</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to apply</entry>
- </row>
-
- <row>
- <entry><parameter>flag</parameter></entry>
- <entry>Sleeping/non-sleeping &man.malloc.9;; see
- below</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated IP fragment
- reassembly queue. The <parameter>flag</parameter> field may
- be one of <symbol>M_WAITOK</symbol> and
- <symbol>M_NOWAIT</symbol>, and should be employed to avoid
- performing a sleeping &man.malloc.9; during this
- initialization call. IP fragment reassembly queue
- allocation frequently occurs in performance sensitive
- environments, and the implementation should be careful to
- avoid sleeping or long-lived operations. This entry point
- is permitted to fail resulting in the failure to allocate
- the IP fragment reassembly queue.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-mbuf">
- <title><function>&mac.mpo;_init_mbuf_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_mbuf_label</function></funcdef>
-
- <paramdef>int <parameter>flag</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>flag</parameter></entry>
- <entry>Sleeping/non-sleeping &man.malloc.9;; see
- below</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label to initialize</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated mbuf packet
- header (<parameter>mbuf</parameter>). The
- <parameter>flag</parameter> field may be one of
- <symbol>M_WAITOK</symbol> and <symbol>M_NOWAIT</symbol>, and
- should be employed to avoid performing a sleeping
- &man.malloc.9; during this initialization call. Mbuf
- allocation frequently occurs in performance sensitive
- environments, and the implementation should be careful to
- avoid sleeping or long-lived operations. This entry point
- is permitted to fail resulting in the failure to allocate
- the mbuf header.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-mount">
- <title><function>&mac.mpo;_init_mount_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_mount_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>mntlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <!-- XXX: Wording on label descriptions. -->
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mntlabel</parameter></entry>
- <entry>Policy label to be initialized for the mount
- itself</entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>Policy label to be initialized for the file
- system</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the labels on a newly instantiated mount
- point. Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-mount-fs-label">
- <title><function>&mac.mpo;_init_mount_fs_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_mount_fs_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label to be initialized</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly mounted file system.
- Sleeping is permitted</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-pipe-label">
- <title><function>&mac.mpo;_init_pipe_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_pipe_label</function></funcdef>
-
- <paramdef>struct
- label*<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label to be filled in</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize a label for a newly instantiated pipe.
- Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-socket">
- <title><function>&mac.mpo;_init_socket_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_socket_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>flag</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to initialize</entry>
- </row>
-
- <row>
- <entry><parameter>flag</parameter></entry>
- <entry>&man.malloc.9; flags</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize a label for a newly instantiated socket. The
- <parameter>flag</parameter> field may be one of
- <symbol>M_WAITOK</symbol> and <symbol>M_NOWAIT</symbol>, and
- should be employed to avoid performing a sleeping
- &man.malloc.9; during this initialization call.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-socket-peer-label">
- <title><function>&mac.mpo;_init_socket_peer_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_socket_peer_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>flag</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to initialize</entry>
- </row>
-
- <row>
- <entry><parameter>flag</parameter></entry>
- <entry>&man.malloc.9; flags</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the peer label for a newly instantiated
- socket. The <parameter>flag</parameter> field may be one of
- <symbol>M_WAITOK</symbol> and <symbol>M_NOWAIT</symbol>, and
- should be employed to avoid performing a sleeping
- &man.malloc.9; during this initialization call.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-init-proc-label">
- <title><function>&mac.mpo;_init_proc_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_proc_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to initialize</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label for a newly instantiated process.
- Sleeping is permitted.</para>
- </sect3>
-
-
- <sect3 xml:id="mac-mpo-init-vnode">
- <title><function>&mac.mpo;_init_vnode_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_init_vnode_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>New label to initialize</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Initialize the label on a newly instantiated vnode.
- Sleeping is permitted.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-bpfdesc">
- <title><function>&mac.mpo;_destroy_bpfdesc_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_bpfdesc_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>bpfdesc label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a BPF descriptor. In this entry
- point a policy should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-cred">
- <title><function>&mac.mpo;_destroy_cred_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_cred_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a credential. In this entry point,
- a policy module should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-devfsdirent">
- <title><function>&mac.mpo;_destroy_devfsdirent_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_devfsdirent_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a devfs entry. In this entry
- point, a policy module should free any internal storage
- associated with <parameter>label</parameter> so that it may
- be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-ifnet-label">
- <title><function>&mac.mpo;_destroy_ifnet_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_ifnet_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a removed interface. In this entry
- point, a policy module should free any internal storage
- associated with <parameter>label</parameter> so that it may
- be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-ipq-label">
- <title><function>&mac.mpo;_destroy_ipq_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_ipq_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on an IP fragment queue. In this
- entry point, a policy module should free any internal
- storage associated with <parameter>label</parameter> so that
- it may be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-mbuf-label">
- <title><function>&mac.mpo;_destroy_mbuf_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_mbuf_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on an mbuf header. In this entry
- point, a policy module should free any internal storage
- associated with <parameter>label</parameter> so that it may
- be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-mount-label">
- <title><function>&mac.mpo;_destroy_mount_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_mount_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Mount point label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the labels on a mount point. In this entry
- point, a policy module should free the internal storage
- associated with <parameter>mntlabel</parameter> so that they
- may be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-mount">
- <title><function>&mac.mpo;_destroy_mount_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_mount_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>mntlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mntlabel</parameter></entry>
- <entry>Mount point label being destroyed</entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>File system label being destroyed&gt;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the labels on a mount point. In this entry
- point, a policy module should free the internal storage
- associated with <parameter>mntlabel</parameter> and
- <parameter>fslabel</parameter> so that they may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-socket">
- <title><function>&mac.mpo;_destroy_socket_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_socket_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Socket label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a socket. In this entry point, a
- policy module should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-socket-peer-label">
- <title><function>&mac.mpo;_destroy_socket_peer_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_socket_peer_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>peerlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>peerlabel</parameter></entry>
- <entry>Socket peer label being destroyed</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the peer label on a socket. In this entry
- point, a policy module should free any internal storage
- associated with <parameter>label</parameter> so that it may
- be destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-pipe-label">
- <title><function>&mac.mpo;_destroy_pipe_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_pipe_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Pipe label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a pipe. In this entry point, a
- policy module should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-proc-label">
- <title><function>&mac.mpo;_destroy_proc_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_proc_label</function></funcdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Process label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a process. In this entry point, a
- policy module should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-destroy-vnode-label">
- <title><function>&mac.mpo;_destroy_vnode_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_destroy_vnode_label</function></funcdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Process label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Destroy the label on a vnode. In this entry point, a
- policy module should free any internal storage associated
- with <parameter>label</parameter> so that it may be
- destroyed.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-copy-mbuf-label">
- <title><function>&mac.mpo;_copy_mbuf_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_copy_mbuf_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>src</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dest</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>src</parameter></entry>
- <entry>Source label</entry>
- </row>
-
- <row>
- <entry><parameter>dest</parameter></entry>
- <entry>Destination label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Copy the label information in <parameter>src</parameter>
- into <parameter>dest</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-copy-pipe-label">
- <title><function>&mac.mpo;_copy_pipe_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_copy_pipe_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>src</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dest</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>src</parameter></entry>
- <entry>Source label</entry>
- </row>
-
- <row>
- <entry><parameter>dest</parameter></entry>
- <entry>Destination label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Copy the label information in <parameter>src</parameter>
- into <parameter>dest</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-copy-vnode-label">
- <title><function>&mac.mpo;_copy_vnode_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_copy_vnode_label</function></funcdef>
-
- <paramdef>struct label
- *<parameter>src</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dest</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>src</parameter></entry>
- <entry>Source label</entry>
- </row>
-
- <row>
- <entry><parameter>dest</parameter></entry>
- <entry>Destination label</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Copy the label information in <parameter>src</parameter>
- into <parameter>dest</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-cred-label">
- <title><function>&mac.mpo;_externalize_cred_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_cred_label</function></funcdef>
-
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-ifnet-label">
- <title><function>&mac.mpo;_externalize_ifnet_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_ifnet_label</function></funcdef>
-
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-pipe-label">
- <title><function>&mac.mpo;_externalize_pipe_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_pipe_label</function></funcdef>
-
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-socket-label">
- <title><function>&mac.mpo;_externalize_socket_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_socket_label</function></funcdef>
-
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-socket-peer-label">
- <title><function>&mac.mpo;_externalize_socket_peer_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_socket_peer_label</function></funcdef>
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-externalize-vnode-label">
- <title><function>&mac.mpo;_externalize_vnode_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_externalize_vnode_label</function></funcdef>
-
- &mac.externalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.externalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.externalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-internalize-cred-label">
- <title><function>&mac.mpo;_internalize_cred_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_internalize_cred_label</function></funcdef>
-
- &mac.internalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.internalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.internalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-internalize-ifnet-label">
- <title><function>&mac.mpo;_internalize_ifnet_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_internalize_ifnet_label</function></funcdef>
-
- &mac.internalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.internalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.internalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-internalize-pipe-label">
- <title><function>&mac.mpo;_internalize_pipe_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_internalize_pipe_label</function></funcdef>
-
- &mac.internalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.internalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.internalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-internalize-socket-label">
- <title><function>&mac.mpo;_internalize_socket_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_internalize_socket_label</function></funcdef>
-
- &mac.internalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.internalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.internalize.para;
- </sect3>
-
- <sect3 xml:id="mac-mpo-internalize-vnode-label">
- <title><function>&mac.mpo;_internalize_vnode_label</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_internalize_vnode_label</function></funcdef>
-
- &mac.internalize.paramdefs;
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- &mac.internalize.tbody;
- </tgroup>
- </informaltable>
-
- &mac.internalize.para;
- </sect3>
- </sect2>
-
- <sect2 xml:id="mac-label-events">
- <title>Label Events</title>
-
- <para>This class of entry points is used by the MAC framework to
- permit policies to maintain label information on kernel
- objects. For each labeled kernel object of interest to a MAC
- policy, entry points may be registered for relevant life cycle
- events. All objects implement initialization, creation, and
- destruction hooks. Some objects will also implement
- relabeling, allowing user processes to change the labels on
- objects. Some objects will also implement object-specific
- events, such as label events associated with IP reassembly. A
- typical labeled object will have the following life cycle of
- entry points:</para>
-
- <programlisting>Label initialization o
-(object-specific wait) \
-Label creation o
- \
-Relabel events, o--&lt;--.
-Various object-specific, | |
-Access control events ~--&gt;--o
- \
-Label destruction o</programlisting>
-
- <para>Label initialization permits policies to allocate memory
- and set initial values for labels without context for the use
- of the object. The label slot allocated to a policy will be
- zeroed by default, so some policies may not need to perform
- initialization.</para>
-
- <para>Label creation occurs when the kernel structure is
- associated with an actual kernel object. For example, Mbufs
- may be allocated and remain unused in a pool until they are
- required. mbuf allocation causes label initialization on the
- mbuf to take place, but mbuf creation occurs when the mbuf is
- associated with a datagram. Typically, context will be
- provided for a creation event, including the circumstances of
- the creation, and labels of other relevant objects in the
- creation process. For example, when an mbuf is created from a
- socket, the socket and its label will be presented to
- registered policies in addition to the new mbuf and its label.
- Memory allocation in creation events is discouraged, as it may
- occur in performance sensitive ports of the kernel; in
- addition, creation calls are not permitted to fail so a
- failure to allocate memory cannot be reported.</para>
-
- <para>Object specific events do not generally fall into the
- other broad classes of label events, but will generally
- provide an opportunity to modify or update the label on an
- object based on additional context. For example, the label on
- an IP fragment reassembly queue may be updated during the
- <symbol>MAC_UPDATE_IPQ</symbol> entry point as a result of the
- acceptance of an additional mbuf to that queue.</para>
-
- <para>Access control events are discussed in detail in the
- following section.</para>
-
- <para>Label destruction permits policies to release storage or
- state associated with a label during its association with an
- object so that the kernel data structures supporting the
- object may be reused or released.</para>
-
- <para>In addition to labels associated with specific kernel
- objects, an additional class of labels exists: temporary
- labels. These labels are used to store update information
- submitted by user processes. These labels are initialized and
- destroyed as with other label types, but the creation event is
- <symbol>MAC_INTERNALIZE</symbol>, which accepts a user label
- to be converted to an in-kernel representation.</para>
-
- <sect3 xml:id="mac-fs-label-event-ops">
- <title>File System Object Labeling Event Operations</title>
-
- <sect4 xml:id="mac-mpo-associate-vnode-devfs">
- <title><function>&mac.mpo;_associate_vnode_devfs</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_associate_vnode_devfs</function></funcdef>
-
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- <paramdef>struct devfs_dirent
- *<parameter>de</parameter></paramdef>
- <paramdef>struct label
- *<parameter>delabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>Devfs mount point</entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>Devfs file system label
- (<varname>mp-&gt;mnt_fslabel</varname>)</entry>
- </row>
-
- <row>
- <entry><parameter>de</parameter></entry>
- <entry>Devfs directory entry</entry>
- </row>
-
- <row>
- <entry><parameter>delabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>de</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>vnode associated with
- <parameter>de</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill in the label (<parameter>vlabel</parameter>) for
- a newly created devfs vnode based on the devfs directory
- entry passed in <parameter>de</parameter> and its
- label.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-associate-vnode-extattr">
- <title><function>&mac.mpo;_associate_vnode_extattr</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_associate_vnode_extattr</function></funcdef>
-
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>File system mount point</entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>File system label</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Vnode to label</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Attempt to retrieve the label for
- <parameter>vp</parameter> from the file system extended
- attributes. Upon success, the value <literal>0</literal>
- is returned. Should extended attribute retrieval not be
- supported, an accepted fallback is to copy
- <parameter>fslabel</parameter> into
- <parameter>vlabel</parameter>. In the event of an error,
- an appropriate value for <varname>errno</varname> should
- be returned.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-associate-vnode-singlelabel">
- <title><function>&mac.mpo;_associate_vnode_singlelabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_associate_vnode_singlelabel</function></funcdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>File system mount point</entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>File system label</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Vnode to label</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>On non-multilabel file systems, this entry point is
- called to set the policy label for
- <parameter>vp</parameter> based on the file system label,
- <parameter>fslabel</parameter>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-devfs-device">
- <title><function>&mac.mpo;_create_devfs_device</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_devfs_device</function></funcdef>
-
- <paramdef>dev_t <parameter>dev</parameter></paramdef>
- <paramdef>struct devfs_dirent
- *<parameter>devfs_dirent</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>dev</parameter></entry>
- <entry>Device corresponding with
- <parameter>devfs_dirent</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>devfs_dirent</parameter></entry>
- <entry>Devfs directory entry to be labeled.</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Label for <parameter>devfs_dirent</parameter>
- to be filled in.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill out the label on a devfs_dirent being created for
- the passed device. This call will be made when the device
- file system is mounted, regenerated, or a new device is
- made available.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-devfs-directory">
- <title><function>&mac.mpo;_create_devfs_directory</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_devfs_directory</function></funcdef>
-
- <paramdef>char
- *<parameter>dirname</parameter></paramdef>
- <paramdef>int
- <parameter>dirnamelen</parameter></paramdef>
- <paramdef>struct devfs_dirent
- *<parameter>devfs_dirent</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>dirname</parameter></entry>
- <entry>Name of directory being created</entry>
- </row>
-
- <row>
- <entry><parameter>namelen</parameter></entry>
- <entry>Length of string
- <parameter>dirname</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>devfs_dirent</parameter></entry>
- <entry>Devfs directory entry for directory being
- created.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill out the label on a devfs_dirent being created for
- the passed directory. This call will be made when the
- device file system is mounted, regenerated, or a new
- device requiring a specific directory hierarchy is made
- available.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-devfs-symlink">
- <title><function>&mac.mpo;_create_devfs_symlink</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_devfs_symlink</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct devfs_dirent
- *<parameter>dd</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ddlabel</parameter></paramdef>
- <paramdef>struct devfs_dirent
- *<parameter>de</parameter></paramdef>
- <paramdef>struct label
- *<parameter>delabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>Devfs mount point</entry>
- </row>
-
- <row>
- <entry><parameter>dd</parameter></entry>
- <entry>Link destination</entry>
- </row>
-
- <row>
- <entry><parameter>ddlabel</parameter></entry>
- <entry>Label associated with
- <parameter>dd</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>de</parameter></entry>
- <entry>Symlink entry</entry>
- </row>
-
- <row>
- <entry><parameter>delabel</parameter></entry>
- <entry>Label associated with
- <parameter>de</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill in the label (<parameter>delabel</parameter>) for
- a newly created &man.devfs.5; symbolic link entry.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-vnode-extattr">
- <title><function>&mac.mpo;_create_vnode_extattr</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_create_vnode_extattr</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>mount</parameter></entry>
- <entry>File system mount point</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>File system label</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Parent directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Label associated with
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Newly created vnode</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Write out the label for <parameter>vp</parameter> to
- the appropriate extended attribute. If the write
- succeeds, fill in <parameter>vlabel</parameter> with the
- label, and return <returnvalue>0</returnvalue>.
- Otherwise, return an appropriate error.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mount">
- <title><function>&mac.mpo;_create_mount</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mount</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct
- label *<parameter>mnt</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>Object; file system being mounted</entry>
- </row>
-
- <row>
- <entry><parameter>mntlabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>mp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>fslabel</parameter></entry>
- <entry>Policy label for the file system
- <parameter>mp</parameter> mounts.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill out the labels on the mount point being created
- by the passed subject credential. This call will be made
- when a new file system is mounted.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-root-mount">
- <title><function>&mac.mpo;_create_root_mount</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_root_mount</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mntlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fslabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry namest="first" nameend="last">See <xref
- linkend="mac-mpo-create-mount"/>.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Fill out the labels on the mount point being created
- by the passed subject credential. This call will be made
- when the root file system is mounted, after
- &mac.mpo;_create_mount;.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-relabel-vnode">
- <title><function>&mac.mpo;_relabel_vnode</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_relabel_vnode</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vnodelabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>vnode to relabel</entry>
- </row>
-
- <row>
- <entry><parameter>vnodelabel</parameter></entry>
- <entry>Existing policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>New, possibly partial label to replace
- <parameter>vnodelabel</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label on the passed vnode given the passed
- update vnode label and the passed subject
- credential.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-setlabel-vnode-extattr">
- <title><function>&mac.mpo;_setlabel_vnode_extattr</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_setlabel_vnode_extattr</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>intlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Vnode for which the label is being
- written</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>intlabel</parameter></entry>
- <entry>Label to write out</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Write out the policy from
- <parameter>intlabel</parameter> to an extended attribute.
- This is called from
- <function>vop_stdcreatevnode_ea</function>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-update-devfsdirent">
- <title><function>&mac.mpo;_update_devfsdirent</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_update_devfsdirent</function></funcdef>
-
- <paramdef>struct devfs_dirent
- *<parameter>devfs_dirent</parameter></paramdef>
- <paramdef>struct label
- *<parameter>direntlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vnodelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>devfs_dirent</parameter></entry>
- <entry>Object; devfs directory entry</entry>
- </row>
-
- <row>
- <entry><parameter>direntlabel</parameter></entry>
- <entry>Policy label for
- <parameter>devfs_dirent</parameter> to be
- updated.</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Parent vnode</entry>
- <entry>Locked</entry>
- </row>
-
- <row>
- <entry><parameter>vnodelabel</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the <parameter>devfs_dirent</parameter> label
- from the passed devfs vnode label. This call will be made
- when a devfs vnode has been successfully relabeled to
- commit the label change such that it lasts even if the
- vnode is recycled. It will also be made when a symlink is
- created in devfs, following a call to
- <function>mac_vnode_create_from_vnode</function> to
- initialize the vnode label.</para>
- </sect4>
- </sect3>
-
- <sect3 xml:id="mac-ipc-label-ops">
- <title>IPC Object Labeling Event Operations</title>
-
- <sect4 xml:id="mac-mpo-create-mbuf-from-socket">
- <title><function>&mac.mpo;_create_mbuf_from_socket</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_from_socket</function></funcdef>
-
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>m</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Socket</entry>
- <entry>Socket locking WIP</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>socket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>m</parameter></entry>
- <entry>Object; mbuf</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label to fill in for
- <parameter>m</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created mbuf header from the
- passed socket label. This call is made when a new
- datagram or message is generated by the socket and stored
- in the passed mbuf.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-pipe">
- <title><function>&mac.mpo;_create_pipe</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_pipe</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created pipe from the passed
- subject credential. This call is made when a new pipe is
- created.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-socket">
- <title><function>&mac.mpo;_create_socket</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_socket</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>so</parameter></entry>
- <entry>Object; socket to label</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Label to fill in for
- <parameter>so</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created socket from the
- passed subject credential. This call is made when a
- socket is created.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-socket-from-socket">
- <title><function>&mac.mpo;_create_socket_from_socket</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_socket_from_socket</function></funcdef>
-
- <paramdef>struct socket
- *<parameter>oldsocket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldsocketlabel</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>newsocket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newsocketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>oldsocket</parameter></entry>
- <entry>Listening socket</entry>
- </row>
-
- <row>
- <entry><parameter>oldsocketlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>oldsocket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newsocket</parameter></entry>
- <entry>New socket</entry>
- </row>
-
- <row>
- <entry><parameter>newsocketlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>newsocketlabel</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Label a socket, <parameter>newsocket</parameter>,
- newly &man.accept.2;ed, based on the &man.listen.2;
- socket, <parameter>oldsocket</parameter>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-relabel-pipe">
- <title><function>&mac.mpo;_relabel_pipe</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_relabel_pipe</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>oldlabel</parameter></entry>
- <entry>Current policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Policy label update to apply to
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Apply a new label, <parameter>newlabel</parameter>, to
- <parameter>pipe</parameter>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-relabel-socket">
- <title><function>&mac.mpo;_relabel_socket</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_relabel_socket</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>so</parameter></entry>
- <entry>Object; socket</entry>
- </row>
-
- <row>
- <entry><parameter>oldlabel</parameter></entry>
- <entry>Current label for
- <parameter>so</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update for
- <parameter>so</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label on a socket from the passed socket
- label update.</para>
- </sect4>
-
- <sect4 xml:id="mpo-set-socket-peer-from-mbuf">
- <title><function>&mac.mpo;_set_socket_peer_from_mbuf</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_set_socket_peer_from_mbuf</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>First datagram received over socket</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Label for <parameter>mbuf</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>oldlabel</parameter></entry>
- <entry>Current label for the socket</entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Policy label to be filled out for the
- socket</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the peer label on a stream socket from the passed
- mbuf label. This call will be made when the first
- datagram is received by the stream socket, with the
- exception of Unix domain sockets.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-set-socket-peer-from-socket">
- <title><function>&mac.mpo;_set_socket_peer_from_socket</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_set_socket_peer_from_socket</function></funcdef>
- <paramdef>struct socket
- *<parameter>oldsocket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldsocketlabel</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>newsocket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newsocketpeerlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>oldsocket</parameter></entry>
- <entry>Local socket</entry>
- </row>
-
- <row>
- <entry><parameter>oldsocketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>oldsocket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newsocket</parameter></entry>
- <entry>Peer socket</entry>
- </row>
-
- <row>
- <entry><parameter>newsocketpeerlabel</parameter></entry>
- <entry>Policy label to fill in for
- <parameter>newsocket</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <!-- XXX Passed _remote_ socket endpoint ? -->
- <para>Set the peer label on a stream UNIX domain socket from
- the passed remote socket endpoint. This call will be made
- when the socket pair is connected, and will be made for
- both endpoints.</para>
- </sect4>
- </sect3>
-
- <sect3 xml:id="mac-net-labeling-event-ops">
- <title>Network Object Labeling Event Operations</title>
-
- <sect4 xml:id="mac-mpo-create-bpfdesc">
- <title><function>&mac.mpo;_create_bpfdesc</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_bpfdesc</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct bpf_d
- *<parameter>bpf_d</parameter></paramdef>
- <paramdef>struct label
- *<parameter>bpflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>bpf_d</parameter></entry>
- <entry>Object; bpf descriptor</entry>
- </row>
-
- <row>
- <entry><parameter>bpf</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>bpf_d</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created BPF descriptor from
- the passed subject credential. This call will be made
- when a BPF device node is opened by a process with the
- passed subject credential.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-ifnet">
- <title><function>&mac.mpo;_create_ifnet</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_ifnet</function></funcdef>
-
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label to fill in for
- <parameter>ifnet</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created interface. This call
- may be made when a new physical interface becomes
- available to the system, or when a pseudo-interface is
- instantiated during the boot or as a result of a user
- action.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-ipq">
- <title><function>&mac.mpo;_create_ipq</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_ipq</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>fragment</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fragmentlabel</parameter></paramdef>
- <paramdef>struct ipq
- *<parameter>ipq</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ipqlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>fragment</parameter></entry>
- <entry>First received IP fragment</entry>
- </row>
-
- <row>
- <entry><parameter>fragmentlabel</parameter></entry>
- <entry>Policy label for
- <parameter>fragment</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>ipq</parameter></entry>
- <entry>IP reassembly queue to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>ipqlabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>ipq</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly created IP fragment
- reassembly queue from the mbuf header of the first
- received fragment.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-datagram-from-ipq">
- <title><function>&mac.mpo;_create_datagram_from_ipq</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_create_datagram_from_ipq</function></funcdef>
-
- <paramdef>struct ipq
- *<parameter>ipq</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ipqlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>datagram</parameter></paramdef>
- <paramdef>struct label
- *<parameter>datagramlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>ipq</parameter></entry>
- <entry>IP reassembly queue</entry>
- </row>
-
- <row>
- <entry><parameter>ipqlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ipq</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>datagram</parameter></entry>
- <entry>Datagram to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>datagramlabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>datagramlabel</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on a newly reassembled IP datagram from
- the IP fragment reassembly queue from which it was
- generated.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-fragment">
- <title><function>&mac.mpo;_create_fragment</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_fragment</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>datagram</parameter></paramdef>
- <paramdef>struct label
- *<parameter>datagramlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>fragment</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fragmentlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>datagram</parameter></entry>
- <entry>Datagram</entry>
- </row>
-
- <row>
- <entry><parameter>datagramlabel</parameter></entry>
- <entry>Policy label for
- <parameter>datagram</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>fragment</parameter></entry>
- <entry>Fragment to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>fragmentlabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>datagram</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created IP
- fragment from the label on the mbuf header of the datagram
- it was generate from.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-from-mbuf">
- <title><function>&mac.mpo;_create_mbuf_from_mbuf</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_from_mbuf</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>oldmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldmbuflabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>newmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newmbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>oldmbuf</parameter></entry>
- <entry>Existing (source) mbuf</entry>
- </row>
-
- <row>
- <entry><parameter>oldmbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>oldmbuf</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newmbuf</parameter></entry>
- <entry>New mbuf to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>newmbuflabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>newmbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram from the mbuf header of an existing datagram.
- This call may be made in a number of situations, including
- when an mbuf is re-allocated for alignment
- purposes.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-linklayer">
- <title><function>&mac.mpo;_create_mbuf_linklayer</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_linklayer</function></funcdef>
-
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>mbuf header for new datagram</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>mbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram generated for the purposes of a link layer
- response for the passed interface. This call may be made
- in a number of situations, including for ARP or ND6
- responses in the IPv4 and IPv6 stacks.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-from-bpfdesc">
- <title><function>&mac.mpo;_create_mbuf_from_bpfdesc</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_from_bpfdesc</function></funcdef>
-
- <paramdef>struct bpf_d
- *<parameter>bpf_d</parameter></paramdef>
- <paramdef>struct label
- *<parameter>bpflabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>bpf_d</parameter></entry>
- <entry>BPF descriptor</entry>
- </row>
-
- <row>
- <entry><parameter>bpflabel</parameter></entry>
- <entry>Policy label for
- <parameter>bpflabel</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>New mbuf to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label to fill in for
- <parameter>mbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram generated using the passed BPF descriptor. This
- call is made when a write is performed to the BPF device
- associated with the passed BPF descriptor.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-from-ifnet">
- <title><function>&mac.mpo;_create_mbuf_from_ifnet</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_from_ifnet</function></funcdef>
-
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnetlabel</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>mbuf header for new datagram</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>mbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram generated from the passed network
- interface.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-multicast-encap">
- <title><function>&mac.mpo;_create_mbuf_multicast_encap</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_multicast_encap</function></funcdef>
- <paramdef>struct mbuf
- *<parameter>oldmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldmbuflabel</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>newmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newmbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>oldmbuf</parameter></entry>
- <entry>mbuf header for existing datagram</entry>
- </row>
-
- <row>
- <entry><parameter>oldmbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>oldmbuf</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newmbuf</parameter></entry>
- <entry>mbuf header to be labeled for new
- datagram</entry>
- </row>
-
- <row>
- <entry><parameter>newmbuflabel</parameter></entry>
- <entry>Policy label to be filled in for
- <parameter>newmbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram generated from the existing passed datagram when
- it is processed by the passed multicast encapsulation
- interface. This call is made when an mbuf is to be
- delivered using the virtual interface.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-mbuf-netlayer">
- <title><function>&mac.mpo;_create_mbuf_netlayer</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_mbuf_netlayer</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>oldmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>oldmbuflabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>newmbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newmbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>oldmbuf</parameter></entry>
- <entry>Received datagram</entry>
- </row>
-
- <row>
- <entry><parameter>oldmbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>oldmbuf</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newmbuf</parameter></entry>
- <entry>Newly created datagram</entry>
- </row>
-
- <row>
- <entry><parameter>newmbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>newmbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label on the mbuf header of a newly created
- datagram generated by the IP stack in response to an
- existing received datagram
- (<parameter>oldmbuf</parameter>). This call may be made
- in a number of situations, including when responding to
- ICMP request datagrams.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-fragment-match">
- <title><function>&mac.mpo;_fragment_match</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_fragment_match</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>fragment</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fragmentlabel</parameter></paramdef>
- <paramdef>struct ipq
- *<parameter>ipq</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ipqlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>fragment</parameter></entry>
- <entry>IP datagram fragment</entry>
- </row>
-
- <row>
- <entry><parameter>fragmentlabel</parameter></entry>
- <entry>Policy label for
- <parameter>fragment</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>ipq</parameter></entry>
- <entry>IP fragment reassembly queue</entry>
- </row>
-
- <row>
- <entry><parameter>ipqlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ipq</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether an mbuf header containing an IP
- datagram (<parameter>fragment</parameter>) fragment
- matches the label of the passed IP fragment reassembly
- queue (<parameter>ipq</parameter>). Return
- (<returnvalue>1</returnvalue>) for a successful match, or
- (<returnvalue>0</returnvalue>) for no match. This call is
- made when the IP stack attempts to find an existing
- fragment reassembly queue for a newly received fragment;
- if this fails, a new fragment reassembly queue may be
- instantiated for the fragment. Policies may use this
- entry point to prevent the reassembly of otherwise
- matching IP fragments if policy does not permit them to be
- reassembled based on the label or other
- information.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-ifnet-relabel">
- <title><function>&mac.mpo;_relabel_ifnet</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_relabel_ifnet</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Object; Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update to apply to
- <parameter>ifnet</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label of network interface,
- <parameter>ifnet</parameter>, based on the passed update
- label, <parameter>newlabel</parameter>, and the passed
- subject credential, <parameter>cred</parameter>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-update-ipq">
- <title><function>&mac.mpo;_update_ipq</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_update_ipq</function></funcdef>
-
- <paramdef>struct mbuf
- *<parameter>fragment</parameter></paramdef>
- <paramdef>struct label
- *<parameter>fragmentlabel</parameter></paramdef>
- <paramdef>struct ipq
- *<parameter>ipq</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ipqlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>IP fragment</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>mbuf</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>ipq</parameter></entry>
- <entry>IP fragment reassembly queue</entry>
- </row>
-
- <row>
- <entry><parameter>ipqlabel</parameter></entry>
- <entry>Policy label to be updated for
- <parameter>ipq</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label on an IP fragment reassembly queue
- (<parameter>ipq</parameter>) based on the acceptance of
- the passed IP fragment mbuf header
- (<parameter>mbuf</parameter>).</para>
- </sect4>
- </sect3>
-
- <sect3 xml:id="mac-proc-labeling-event-ops">
- <title>Process Labeling Event Operations</title>
-
- <sect4 xml:id="mac-mpo-create-cred">
- <title><function>&mac.mpo;_create_cred</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_cred</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>parent_cred</parameter></paramdef>
- <paramdef>struct ucred
- *<parameter>child_cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>parent_cred</parameter></entry>
- <entry>Parent subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>child_cred</parameter></entry>
- <entry>Child subject credential</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Set the label of a newly created subject credential
- from the passed subject credential. This call will be
- made when &man.crcopy.9; is invoked on a newly created
- <type>struct ucred</type>. This call should not be
- confused with a process forking or creation event.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-execve-transition">
- <title><function>&mac.mpo;_execve_transition</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_execve_transition</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>old</parameter></paramdef>
- <paramdef>struct ucred
- *<parameter>new</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vnodelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>old</parameter></entry>
- <entry>Existing subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>new</parameter></entry>
- <entry>New subject credential to be labeled</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>File to execute</entry> <entry>Locked</entry>
- </row>
-
- <row>
- <entry><parameter>vnodelabel</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label of a newly created subject credential
- (<parameter>new</parameter>) from the passed existing
- subject credential (<parameter>old</parameter>) based on a
- label transition caused by executing the passed vnode
- (<parameter>vp</parameter>). This call occurs when a
- process executes the passed vnode and one of the policies
- returns a success from the
- <function>mpo_execve_will_transition</function> entry
- point. Policies may choose to implement this call simply
- by invoking <function>mpo_create_cred</function> and
- passing the two subject credentials so as not to implement
- a transitioning event. Policies should not leave this
- entry point unimplemented if they implement
- <function>mpo_create_cred</function>, even if they do not
- implement
- <function>mpo_execve_will_transition</function>.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-execve-will-transition">
- <title><function>&mac.mpo;_execve_will_transition</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_execve_will_transition</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>old</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vnodelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>old</parameter></entry>
- <entry>Subject credential prior to
- &man.execve.2;</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>File to execute</entry>
- </row>
-
- <row>
- <entry><parameter>vnodelabel</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the policy will want to perform a
- transition event as a result of the execution of the
- passed vnode by the passed subject credential. Return
- <returnvalue>1</returnvalue> if a transition is required,
- <returnvalue>0</returnvalue> if not. Even if a policy
- returns <returnvalue>0</returnvalue>, it should behave
- correctly in the presence of an unexpected invocation of
- <function>mpo_execve_transition</function>, as that call
- may happen as a result of another policy requesting a
- transition.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-proc0">
- <title><function>&mac.mpo;_create_proc0</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_proc0</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential to be filled in</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Create the subject credential of process 0, the parent
- of all kernel processes.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-create-proc1">
- <title><function>&mac.mpo;_create_proc1</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_create_proc1</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential to be filled in</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Create the subject credential of process 1, the parent
- of all user processes.</para>
- </sect4>
-
- <sect4 xml:id="mac-mpo-relabel-cred">
- <title><function>&mac.mpo;_relabel_cred</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_relabel_cred</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update to apply to
- <parameter>cred</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Update the label on a subject credential from the
- passed update label.</para>
- </sect4>
-
- </sect3>
- </sect2>
-
- <sect2 xml:id="mac-access-control-checks">
- <title>Access Control Checks</title>
-
- <para>Access control entry points permit policy modules to
- influence access control decisions made by the kernel.
- Generally, although not always, arguments to an access control
- entry point will include one or more authorizing credentials,
- information (possibly including a label) for any other objects
- involved in the operation. An access control entry point may
- return 0 to permit the operation, or an &man.errno.2; error
- value. The results of invoking the entry point across various
- registered policy modules will be composed as follows: if all
- modules permit the operation to succeed, success will be
- returned. If one or modules returns a failure, a failure will
- be returned. If more than one module returns a failure, the
- errno value to return to the user will be selected using the
- following precedence, implemented by the
- <function>error_select()</function> function in
- <filename>kern_mac.c</filename>:</para>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>Most precedence</entry>
- <entry><errorcode>EDEADLK</errorcode></entry>
- </row>
-
- <row>
- <entry/>
- <entry><errorcode>EINVAL</errorcode></entry>
- </row>
-
- <row>
- <entry/>
- <entry><errorcode>ESRCH</errorcode></entry>
- </row>
-
- <row>
- <entry/>
- <entry>EACCES</entry>
- </row>
-
- <row>
- <entry>Least precedence</entry>
- <entry>EPERM</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>If none of the error values returned by all modules are
- listed in the precedence chart then an arbitrarily selected
- value from the set will be returned. In general, the rules
- provide precedence to errors in the following order: kernel
- failures, invalid arguments, object not present, access not
- permitted, other.</para>
-
- <sect3 xml:id="mac-mpo-bpfdesc-check-receive-from-ifnet">
- <title><function>&mac.mpo;_check_bpfdesc_receive</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_bpfdesc_receive</function></funcdef>
-
- <paramdef>struct bpf_d
- *<parameter>bpf_d</parameter></paramdef>
- <paramdef>struct label
- *<parameter>bpflabel</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>bpf_d</parameter></entry>
- <entry>Subject; BPF descriptor</entry>
- </row>
-
- <row>
- <entry><parameter>bpflabel</parameter></entry>
- <entry>Policy label for
- <parameter>bpf_d</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Object; network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the MAC framework should permit
- datagrams from the passed interface to be delivered to the
- buffers of the passed BPF descriptor. Return
- (<returnvalue>0</returnvalue>) for success, or an
- <varname>errno</varname> value for failure Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches,
- <errorcode>EPERM</errorcode> for lack of privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kenv-dump">
- <title><function>&mac.mpo;_check_kenv_dump</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kenv_dump</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- retrieve the kernel environment (see &man.kenv.2;).</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kenv-get">
- <title><function>&mac.mpo;_check_kenv_get</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kenv_get</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>char *<parameter>name</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>name</parameter></entry>
- <entry>Kernel environment variable name</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- retrieve the value of the specified kernel environment
- variable.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kenv-set">
- <title><function>&mac.mpo;_check_kenv_set</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kenv_set</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>char *<parameter>name</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>name</parameter></entry>
- <entry>Kernel environment variable name</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to set
- the specified kernel environment variable.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kenv-unset">
- <title><function>&mac.mpo;_check_kenv_unset</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kenv_unset</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>char *<parameter>name</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>name</parameter></entry>
- <entry>Kernel environment variable name</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to unset
- the specified kernel environment variable.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kld-load">
- <title><function>&mac.mpo;_check_kld_load</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kld_load</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Kernel module vnode</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to load
- the specified module file.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kld-stat">
- <title><function>&mac.mpo;_check_kld_stat</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kld_stat</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- retrieve a list of loaded kernel module files and associated
- statistics.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-kld-unload">
- <title><function>&mac.mpo;_check_kld_unload</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_kld_unload</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- unload a kernel module.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-ioctl">
- <title><function>&mac.mpo;_check_pipe_ioctl</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_ioctl</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- <paramdef>unsigned long
- <parameter>cmd</parameter></paramdef>
- <paramdef>void *<parameter>data</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cmd</parameter></entry>
- <entry>&man.ioctl.2; command</entry>
- </row>
-
- <row>
- <entry><parameter>data</parameter></entry>
- <entry>&man.ioctl.2; data</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to make
- the specified &man.ioctl.2; call.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-poll">
- <title><function>&mac.mpo;_check_pipe_poll</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_poll</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to poll
- <parameter>pipe</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-read">
- <title><function>&mac.mpo;_check_pipe_read</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_read</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed read
- access to <parameter>pipe</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-relabel">
- <title><function>&mac.mpo;_check_pipe_relabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_relabel</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Current policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update to
- <parameter>pipelabel</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- relabel <parameter>pipe</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-stat">
- <title><function>&mac.mpo;_check_pipe_stat</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_stat</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- retrieve statistics related to
- <parameter>pipe</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-pipe-write">
- <title><function>&mac.mpo;_check_pipe_write</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_pipe_write</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct pipe
- *<parameter>pipe</parameter></paramdef>
- <paramdef>struct label
- *<parameter>pipelabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>pipe</parameter></entry>
- <entry>Pipe</entry>
- </row>
-
- <row>
- <entry><parameter>pipelabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>pipe</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to write
- to <parameter>pipe</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-bind">
- <title><function>&mac.mpo;_check_socket_bind</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_bind</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>socket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- <paramdef>struct sockaddr
- *<parameter>sockaddr</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Socket to be bound</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>socket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>sockaddr</parameter></entry>
- <entry>Address of
- <parameter>socket</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-connect">
- <title><function>&mac.mpo;_check_socket_connect</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_connect</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>socket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- <paramdef>struct sockaddr
- *<parameter>sockaddr</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Socket to be connected</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>socket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>sockaddr</parameter></entry>
- <entry>Address of
- <parameter>socket</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential
- (<parameter>cred</parameter>) can connect the passed socket
- (<parameter>socket</parameter>) to the passed socket address
- (<parameter>sockaddr</parameter>). Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches,
- <errorcode>EPERM</errorcode> for lack of privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-socket-receive">
- <title><function>&mac.mpo;_check_socket_receive</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_receive</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>so</parameter></entry>
- <entry>Socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>so</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- receive information from the socket
- <parameter>so</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-socket-send">
- <title><function>&mac.mpo;_check_socket_send</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_send</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>so</parameter></entry>
- <entry>Socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>so</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to send
- information across the socket
- <parameter>so</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-cred-visible">
- <title><function>&mac.mpo;_check_cred_visible</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_cred_visible</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>u1</parameter></paramdef>
- <paramdef>struct ucred
- *<parameter>u2</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>u1</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>u2</parameter></entry>
- <entry>Object credential</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential
- <parameter>u1</parameter> can <quote>see</quote> other
- subjects with the passed subject credential
- <parameter>u2</parameter>. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches,
- <errorcode>EPERM</errorcode> for lack of privilege, or
- <errorcode>ESRCH</errorcode> to hide visibility. This call
- may be made in a number of situations, including
- inter-process status sysctl's used by <command>ps</command>,
- and in procfs lookups.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-visible">
- <title><function>&mac.mpo;_check_socket_visible</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_visible</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>socket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Object; socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>socket</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-ifnet-relabel">
- <title><function>&mac.mpo;_check_ifnet_relabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_ifnet_relabel</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Object; network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Existing policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Policy label update to later be applied to
- <parameter>ifnet</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can relabel the
- passed network interface to the passed label update.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-relabel">
- <title><function>&mac.mpo;_check_socket_relabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_relabel</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>socket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Object; socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Existing policy label for
- <parameter>socket</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update to later be applied to
- <parameter>socketlabel</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can relabel the
- passed socket to the passed label update.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-cred-relabel">
- <title><function>&mac.mpo;_check_cred_relabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_cred_relabel</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Label update to later be applied to
- <parameter>cred</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can relabel
- itself to the passed label update.</para>
- </sect3>
-
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-relabel">
- <title><function>&mac.mpo;_check_vnode_relabel</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_relabel</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vnodelabel</parameter></paramdef>
- <paramdef>struct label
- *<parameter>newlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- <entry>Locked</entry>
- </row>
-
- <row>
- <entry><parameter>vnodelabel</parameter></entry>
- <entry>Existing policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>newlabel</parameter></entry>
- <entry>Policy label update to later be applied to
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can relabel the
- passed vnode to the passed label update.</para>
- </sect3>
-
- <sect3 xml:id="mpo-cred-check-mount-stat">
- <title><function>&mac.mpo;_check_mount_stat</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_mount_stat</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct mount
- *<parameter>mp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mountlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>mp</parameter></entry>
- <entry>Object; file system mount</entry>
- </row>
-
- <row>
- <entry><parameter>mountlabel</parameter></entry>
- <entry>Policy label for
- <parameter>mp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <!-- XXX Update ? -->
- <para>Determine whether the subject credential can see the
- results of a statfs performed on the file system. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches
- or <errorcode>EPERM</errorcode> for lack of privilege. This
- call may be made in a number of situations, including during
- invocations of &man.statfs.2; and related calls, as well as
- to determine what file systems to exclude from listings of
- file systems, such as when &man.getfsstat.2; is
- invoked.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-proc-debug">
- <title><function>&mac.mpo;_check_proc_debug</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_proc_debug</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct proc
- *<parameter>proc</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>proc</parameter></entry>
- <entry>Object; process</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can debug the
- passed process. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, <errorcode>EPERM</errorcode> for lack of
- privilege, or <errorcode>ESRCH</errorcode> to hide
- visibility of the target. This call may be made in a number
- of situations, including use of the &man.ptrace.2; and
- &man.ktrace.2; APIs, as well as for some types of procfs
- operations.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-access">
- <title><function>&mac.mpo;_check_vnode_access</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_access</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>flags</parameter></entry>
- <entry>&man.access.2; flags</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine how invocations of &man.access.2; and related
- calls by the subject credential should return when performed
- on the passed vnode using the passed access flags. This
- should generally be implemented using the same semantics
- used in <function>&mac.mpo;_check_vnode_open</function>.
- Return <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-chdir">
- <title><function>&mac.mpo;_check_vnode_chdir</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_chdir</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Object; vnode to &man.chdir.2; into</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label for
- <parameter>dvp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can change the
- process working directory to the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-chroot">
- <title><function>&mac.mpo;_check_vnode_chroot</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_chroot</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>dvp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- &man.chroot.2; into the specified directory
- (<parameter>dvp</parameter>).</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-create">
- <title><function>&mac.mpo;_check_vnode_create</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_create</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- <paramdef>struct vattr
- *<parameter>vap</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label for
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name for
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vap</parameter></entry>
- <entry>vnode attributes for
- <parameter>vap</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can create a
- vnode with the passed parent directory, passed name
- information, and passed attribute information. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of privilege. This
- call may be made in a number of situations, including as a
- result of calls to &man.open.2; with
- <symbol>O_CREAT</symbol>, &man.mkfifo.2;, and others.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-delete">
- <title><function>&mac.mpo;_check_vnode_delete</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_delete</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>void *<parameter>label</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Parent directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label for
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode to delete</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can delete a
- vnode from the passed parent directory and passed name
- information. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, or <errorcode>EPERM</errorcode> for lack of
- privilege. This call may be made in a number of situations,
- including as a result of calls to &man.unlink.2; and
- &man.rmdir.2;. Policies implementing this entry point
- should also implement
- <function>mpo_check_rename_to</function> to authorize
- deletion of objects as a result of being the target of a
- rename.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-deleteacl">
- <title><function>&mac.mpo;_check_vnode_deleteacl</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_deleteacl</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>acl_type_t
- <parameter>type</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- <entry>Locked</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>type</parameter></entry>
- <entry>ACL type</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can delete the
- ACL of passed type from the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-exec">
- <title><function>&mac.mpo;_check_vnode_exec</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_exec</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode to execute</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can execute the
- passed vnode. Determination of execute privilege is made
- separately from decisions about any transitioning event.
- Return <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mpo-cred-check-vnode-getacl">
- <title><function>&mac.mpo;_check_vnode_getacl</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_getacl</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>acl_type_t
- <parameter>type</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>type</parameter></entry>
- <entry>ACL type</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can retrieve
- the ACL of passed type from the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-getextattr">
- <title><function>&mac.mpo;_check_vnode_getextattr</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_getextattr</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int
- <parameter>attrnamespace</parameter></paramdef>
- <paramdef>const char
- *<parameter>name</parameter></paramdef>
- <paramdef>struct uio
- *<parameter>uio</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>attrnamespace</parameter></entry>
- <entry>Extended attribute namespace</entry>
- </row>
-
- <row>
- <entry><parameter>name</parameter></entry>
- <entry>Extended attribute name</entry>
- </row>
-
- <row>
- <entry><parameter>uio</parameter></entry>
- <entry>I/O structure pointer; see &man.uio.9;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can retrieve
- the extended attribute with the passed namespace and name
- from the passed vnode. Policies implementing labeling using
- extended attributes may be interested in special handling of
- operations on those extended attributes. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-link">
- <title><function>&mac.mpo;_check_vnode_link</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_link</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Link destination vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name for the link being
- created</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- create a link to the vnode <parameter>vp</parameter> with
- the name specified by <parameter>cnp</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-mmap">
- <title><function>&mac.mpo;_check_vnode_mmap</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_mmap</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>prot</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Vnode to map</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>prot</parameter></entry>
- <entry>Mmap protections (see &man.mmap.2;)</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to map
- the vnode <parameter>vp</parameter> with the protections
- specified in <parameter>prot</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-mmap-downgrade">
- <title><function>&mac.mpo;_check_vnode_mmap_downgrade</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>void
- <function>&mac.mpo;_check_vnode_mmap_downgrade</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int *<parameter>prot</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry morerows="2">See <xref
- linkend="mac-mpo-check-vnode-mmap"/>.</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>prot</parameter></entry>
- <entry>Mmap protections to be downgraded</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Downgrade the mmap protections based on the subject and
- object labels.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-mprotect">
- <title><function>&mac.mpo;_check_vnode_mprotect</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_mprotect</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>prot</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Mapped vnode</entry>
- </row>
-
- <row>
- <entry><parameter>prot</parameter></entry>
- <entry>Memory protections</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to set
- the specified memory protections on memory mapped from the
- vnode <parameter>vp</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-poll">
- <title><function>&mac.mpo;_check_vnode_poll</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_poll</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>active_cred</parameter></paramdef>
- <paramdef>struct ucred
- *<parameter>file_cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>active_cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>file_cred</parameter></entry>
- <entry>Credential associated with the <type>struct
- file</type></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Polled vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to poll
- the vnode <parameter>vp</parameter>.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-rename-from">
- <title><function>&mac.mpo;_check_vnode_rename_from</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_vnode_rename_from</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Vnode to be renamed</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- rename the vnode <parameter>vp</parameter> to something
- else.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-vnode-rename-to">
- <title><function>&mac.mpo;_check_vnode_rename_to</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_rename_to</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>dvp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>dlabel</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>samedir</parameter></paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label associated with
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Overwritten vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label associated with
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>samedir</parameter></entry>
- <entry>Boolean; <literal>1</literal> if the source and
- destination directories are the same</entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Destination component name</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- rename to the vnode <parameter>vp</parameter>, into the
- directory <parameter>dvp</parameter>, or to the name
- represented by <parameter>cnp</parameter>. If there is no
- existing file to overwrite, <parameter>vp</parameter> and
- <parameter>label</parameter> will be NULL.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-listen">
- <title><function>&mac.mpo;_check_socket_listen</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_listen</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>socket</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>socket</parameter></entry>
- <entry>Object; socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>socket</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can listen on
- the passed socket. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-lookup">
- <title><function>&mac.mpo;_check_vnode_lookup</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_lookup</function></funcdef>
-
- <paramdef>struct ucred *<parameter/>cred</paramdef>
- <paramdef>struct vnode *<parameter/>dvp</paramdef>
- <paramdef>struct label *<parameter/>dlabel</paramdef>
- <paramdef>struct componentname
- *<parameter>cnp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label for
- <parameter>dvp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>cnp</parameter></entry>
- <entry>Component name being looked up</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can perform a
- lookup in the passed directory vnode for the passed name.
- Return <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-open">
- <title><function>&mac.mpo;_check_vnode_open</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_open</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int <parameter>acc_mode</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>acc_mode</parameter></entry>
- <entry>&man.open.2; access mode</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can perform an
- open operation on the passed vnode with the passed access
- mode. Return <returnvalue>0</returnvalue> for success, or
- an errno value for failure. Suggested failure:
- <errorcode>EACCES</errorcode> for label mismatch, or
- <errorcode>EPERM</errorcode> for lack of privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-readdir">
- <title><function>&mac.mpo;_check_vnode_readdir</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_readdir</function></funcdef>
-
- <paramdef>struct ucred *<parameter/>cred</paramdef>
- <paramdef>struct vnode *<parameter/>dvp</paramdef>
- <paramdef>struct label *<parameter/>dlabel</paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>dvp</parameter></entry>
- <entry>Object; directory vnode</entry>
- </row>
-
- <row>
- <entry><parameter>dlabel</parameter></entry>
- <entry>Policy label for
- <parameter>dvp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can perform a
- <function>readdir</function> operation on the passed
- directory vnode. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-readlink">
- <title><function>&mac.mpo;_check_vnode_readlink</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_readlink</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can perform a
- <function>readlink</function> operation on the passed
- symlink vnode. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, or <errorcode>EPERM</errorcode> for lack of
- privilege. This call may be made in a number of situations,
- including an explicit <function>readlink</function> call by
- the user process, or as a result of an implicit
- <function>readlink</function> during a name lookup by the
- process.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-revoke">
- <title><function>&mac.mpo;_check_vnode_revoke</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_revoke</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can revoke
- access to the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setacl">
- <title><function>&mac.mpo;_check_vnode_setacl</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setacl</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>acl_type_t
- <parameter>type</parameter></paramdef>
- <paramdef>struct acl
- *<parameter>acl</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>type</parameter></entry>
- <entry>ACL type</entry>
- </row>
-
- <row>
- <entry><parameter>acl</parameter></entry>
- <entry>ACL</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- passed ACL of passed type on the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setextattr">
- <title><function>&mac.mpo;_check_vnode_setextattr</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setextattr</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>int
- <parameter>attrnamespace</parameter></paramdef>
- <paramdef>const char
- *<parameter>name</parameter></paramdef>
- <paramdef>struct uio
- *<parameter>uio</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>attrnamespace</parameter></entry>
- <entry>Extended attribute namespace</entry>
- </row>
-
- <row>
- <entry><parameter>name</parameter></entry>
- <entry>Extended attribute name</entry>
- </row>
-
- <row>
- <entry><parameter>uio</parameter></entry>
- <entry>I/O structure pointer; see &man.uio.9;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- extended attribute of passed name and passed namespace on
- the passed vnode. Policies implementing security labels
- backed into extended attributes may want to provide
- additional protections for those attributes. Additionally,
- policies should avoid making decisions based on the data
- referenced from <parameter>uio</parameter>, as there is a
- potential race condition between this check and the actual
- operation. The <parameter>uio</parameter> may also be
- <literal>NULL</literal> if a delete operation is being
- performed. Return <returnvalue>0</returnvalue> for success,
- or an <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setflags">
- <title><function>&mac.mpo;_check_vnode_setflags</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setflags</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>u_long <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>flags</parameter></entry>
- <entry>File flags; see &man.chflags.2;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- passed flags on the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setmode">
- <title><function>&mac.mpo;_check_vnode_setmode</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setmode</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>mode_t <parameter>mode</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mode</parameter></entry>
- <entry>File mode; see &man.chmod.2;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- passed mode on the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setowner">
- <title><function>&mac.mpo;_check_vnode_setowner</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setowner</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- <paramdef>uid_t <parameter>uid</parameter></paramdef>
- <paramdef>gid_t <parameter>gid</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>uid</parameter></entry>
- <entry>User ID</entry>
- </row>
-
- <row>
- <entry><parameter>gid</parameter></entry>
- <entry>Group ID</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- passed uid and passed gid as file uid and file gid on the
- passed vnode. The IDs may be set to (<literal>-1</literal>)
- to request no update. Return <returnvalue>0</returnvalue>
- for success, or an <varname>errno</varname> value for
- failure. Suggested failure: <errorcode>EACCES</errorcode>
- for label mismatch, or <errorcode>EPERM</errorcode> for lack
- of privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-setutimes">
- <title><function>&mac.mpo;_check_vnode_setutimes</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_setutimes</function></funcdef>
-
- <paramdef>struct ucred *<parameter/>cred</paramdef>
- <paramdef>struct vnode *<parameter/>vp</paramdef>
- <paramdef>struct label *<parameter/>label</paramdef>
- <paramdef>struct timespec <parameter/>atime</paramdef>
- <paramdef>struct timespec <parameter/>mtime</paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vp</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>atime</parameter></entry>
- <entry>Access time; see &man.utimes.2;</entry>
- </row>
-
- <row>
- <entry><parameter>mtime</parameter></entry>
- <entry>Modification time; see &man.utimes.2;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can set the
- passed access timestamps on the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-proc-sched">
- <title><function>&mac.mpo;_check_proc_sched</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_proc_sched</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>ucred</parameter></paramdef>
- <paramdef>struct proc
- *<parameter>proc</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>proc</parameter></entry>
- <entry>Object; process</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can change the
- scheduling parameters of the passed process. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- <errorcode>EPERM</errorcode> for lack of privilege, or
- <errorcode>ESRCH</errorcode> to limit visibility.</para>
-
- <para>See &man.setpriority.2; for more information.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-proc-signal">
- <title><function>&mac.mpo;_check_proc_signal</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_proc_signal</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct proc
- *<parameter>proc</parameter></paramdef>
- <paramdef>int <parameter>signal</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>proc</parameter></entry>
- <entry>Object; process</entry>
- </row>
-
- <row>
- <entry><parameter>signal</parameter></entry>
- <entry>Signal; see &man.kill.2;</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can deliver the
- passed signal to the passed process. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- <errorcode>EPERM</errorcode> for lack of privilege, or
- <errorcode>ESRCH</errorcode> to limit visibility.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-vnode-stat">
- <title><function>&mac.mpo;_check_vnode_stat</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_vnode_stat</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>label</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Object; vnode</entry>
- </row>
-
- <row>
- <entry><parameter>label</parameter></entry>
- <entry>Policy label for
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential can
- <function>stat</function> the passed vnode. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
-
- <para>See &man.stat.2; for more information.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-ifnet-transmit">
- <title><function>&mac.mpo;_check_ifnet_transmit</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_ifnet_transmit</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>Object; mbuf to be sent</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>mbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the network interface can transmit the
- passed mbuf. Return <returnvalue>0</returnvalue> for
- success, or an <varname>errno</varname> value for failure.
- Suggested failure: <errorcode>EACCES</errorcode> for label
- mismatch, or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-cred-check-socket-deliver">
- <title><function>&mac.mpo;_check_socket_deliver</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_deliver</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct ifnet
- *<parameter>ifnet</parameter></paramdef>
- <paramdef>struct label
- *<parameter>ifnetlabel</parameter></paramdef>
- <paramdef>struct mbuf
- *<parameter>mbuf</parameter></paramdef>
- <paramdef>struct label
- *<parameter>mbuflabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>ifnet</parameter></entry>
- <entry>Network interface</entry>
- </row>
-
- <row>
- <entry><parameter>ifnetlabel</parameter></entry>
- <entry>Policy label for
- <parameter>ifnet</parameter></entry>
- </row>
-
- <row>
- <entry><parameter>mbuf</parameter></entry>
- <entry>Object; mbuf to be delivered</entry>
- </row>
-
- <row>
- <entry><parameter>mbuflabel</parameter></entry>
- <entry>Policy label for
- <parameter>mbuf</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the socket may receive the datagram
- stored in the passed mbuf header. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failures: <errorcode>EACCES</errorcode> for label mismatch,
- or <errorcode>EPERM</errorcode> for lack of
- privilege.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-socket-visible">
- <title><function>&mac.mpo;_check_socket_visible</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_socket_visible</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- <paramdef>struct socket
- *<parameter>so</parameter></paramdef>
- <paramdef>struct label
- *<parameter>socketlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter></entry>
- <entry>Subject credential</entry>
- <entry>Immutable</entry>
- </row>
-
- <row>
- <entry><parameter>so</parameter></entry>
- <entry>Object; socket</entry>
- </row>
-
- <row>
- <entry><parameter>socketlabel</parameter></entry>
- <entry>Policy label for
- <parameter>so</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject credential cred can "see"
- the passed socket (<parameter>socket</parameter>) using
- system monitoring functions, such as those employed by
- &man.netstat.8; and &man.sockstat.1;. Return
- <returnvalue>0</returnvalue> for success, or an
- <varname>errno</varname> value for failure. Suggested
- failure: <errorcode>EACCES</errorcode> for label mismatches,
- <errorcode>EPERM</errorcode> for lack of privilege, or
- <errorcode>ESRCH</errorcode> to hide visibility.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-system-acct">
- <title><function>&mac.mpo;_check_system_acct</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_system_acct</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>ucred</parameter></paramdef>
- <paramdef>struct vnode
- *<parameter>vp</parameter></paramdef>
- <paramdef>struct label
- *<parameter>vlabel</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>ucred</parameter></entry>
- <entry>Subject credential</entry>
- </row>
-
- <row>
- <entry><parameter>vp</parameter></entry>
- <entry>Accounting file; &man.acct.5;</entry>
- </row>
-
- <row>
- <entry><parameter>vlabel</parameter></entry>
- <entry>Label associated with
- <parameter>vp</parameter></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>Determine whether the subject should be allowed to
- enable accounting, based on its label and the label of the
- accounting log file.</para>
- </sect3>
-
- <sect3 xml:id="mac-mpo-check-system-nfsd">
- <title><function>&mac.mpo;_check_system_nfsd</function></title>
-
- <funcsynopsis>
- <funcprototype>
- <funcdef>int
- <function>&mac.mpo;_check_system_nfsd</function></funcdef>
-
- <paramdef>struct ucred
- *<parameter>cred</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <informaltable frame="none" pgwide="1">
- <tgroup cols="3">
- &mac.thead;
-
- <tbody>
- <row>
- <entry><parameter>cred</parameter>