6.7. MAC策略入口函数参考
上一页 | 第 6 章 TrustedBSD MAC 框架 | 下一页

## 6.7. MAC策略入口函数参考

### 6.7.1. 通用的模块入口函数

#### 6.7.1.1. `mpo_init`

`void fsfuncmpo_init(` | conf`)`; |

`struct mac_policy_conf *conf`;

参数 | 说明 | 锁定
--- | --- | ---
`conf` | MAC 策略定义 |

策略加载事件。当前进程正持有策略链表上的互斥锁，因此是非睡眠的，对其他内核子系统的调用也须慎重。 如果需要在策略初始化阶段进行可能造成睡眠阻塞的存储分配操作，可以将它们放在一个单独的模块 SYSINIT() 过程中集中进行。

#### 6.7.1.2. `mpo_destroy`

`void fsfuncmpo_destroy(` | conf`)`; |

`struct mac_policy_conf *conf`;

参数 | 说明 | 锁定
--- | --- | ---
`conf` | MAC 策略定义 |

策略加载事件。必须持有策略链表互斥锁，因此需要慎重行事。

#### 6.7.1.3. `mpo_syscall`

`int fsfuncmpo_syscall(` | td, |
| call, |
| arg`)`; |

`struct thread *td`;
`int call`;
`void *arg`;

参数 | 说明 | 锁定
--- | --- | ---
`td` | 调用线程 |
`call` | 策略特有的系统调用编号 |
`arg` | 系统调用参数的指针 |

该入口函数提供策略复用的系统调用，这样策略模块不需要为其向用户进程提供的每一个额外服务而注册专用的系统调用。 由应用程序提供的策略注册名字来确定提供其所申请服务的特定策略，所有参数将通过该入口函数传递给被调用的策略。 当实现新服务时，安全模块必须在必要时通过 MAC 框架调用相应的访问控制检查机制。 比方说，假如一个策略实现了某种额外的信号功能，那么它应该调用相关的信号访问控制检查，以接受 MAC 框架中注册的其他策略的检查。

### 注意:

不同的模块需要并发地手动进行`copyin()`拷贝系统调用数据。

#### 6.7.1.4. `mpo_thread_userret`

`void fsfuncmpo_thread_userret(` | td`)`; |

`struct thread *td`;

参数 | 说明 | 锁定
--- | --- | ---
`td` | 返回线程 |

使用该入口函数，策略模块能够在线程返回用户空间时（系统调用返回、异常返回等等）进行 MAC 相关的处理工作。 使用动态进程标记的策略需要使用该入口函数，因为在处理系统调用的过程中，并不是在任意时刻都能申请到进程锁的； 进程的标记可能表示传统的认证信息、进程历史记录或者其他数据。为使用该入口函数，对进程信任状所作的修改 可能被存放在 `p_label` ,该域受一个进程级自旋锁的保护；接下来，设置线程级的`TDF_ASTPENDING` 标志位和进程级的`PS_MACPENDM`标志位，表明将调度一个对 userret 入口函数的调用。通过该入口函数， 策略可以在相对简单的同步上下文中创建信任状的替代品。策略编程人员必须清楚，需要保证与调度一个 AST 相关的事件执行次序， 同时所执行的 AST 可能很复杂，而且在处理多线程应用程序时可能被重入。

### 6.7.2. 操作标记

#### 6.7.2.1. `mpo_init_bpfdesc_label`

`void fsfuncmpo_init_bpfdesc_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被应用的新标记 |

为一个新近实例化的 bpfdesc（BPF 描述子）初始化标记。可以睡眠。

#### 6.7.2.2. `mpo_init_cred_label`

`void fsfuncmpo_init_cred_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的新标记 |

为一个新近实例化的用户信任状初始化标记。可以睡眠。

#### 6.7.2.3. `mpo_init_devfsdirent_label`

`void fsfuncmpo_init_devfsdirent_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被应用的新标记 |

为一个新近实例化的 devfs　表项初始化标记。可以睡眠。

#### 6.7.2.4. `mpo_init_ifnet_label`

`void fsfuncmpo_init_ifnet_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被应用的新标记 |

为一个新近实例化的网络接口初始化标记。可以睡眠。

#### 6.7.2.5. `mpo_init_ipq_label`

`void fsfuncmpo_init_ipq_label(` | label, |
| flag`)`; |

`struct label *label`;
`int flag`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被应用的新标记 |
`flag` | 睡眠/不睡眠 malloc(9); 参见下文 |

为一个新近实例化的 IP 分片重组队列初始化标记。其中的`flag`域可能取M_WAITOK 或M_NOWAIT之一，用来避免在该初始化调用中因为 malloc(9) 而进入睡眠。IP 分片重组队列的分配操作通常是在 对性能有严格要求的环境下进行的，因此实现代码必须小心地避免睡眠和长时间的操作。IP 分片重组队列分配操作失败时上述入口函数将失败返回。

#### 6.7.2.6. `mpo_init_mbuf_label`

`void fsfuncmpo_init_mbuf_label(` | flag, |
| label`)`; |

`int flag`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`flag` | 睡眠/不睡眠 malloc(9); 参见下文 |
`label` | 将被初始化的策略标记 |

为一个新近实例化的 mbuf 数据包头部（`mbuf`）初始化标记。 其中的`flag`的值可能取M_WAITOK和M_NOWAIT之一， 用来避免在该初始化调用中因为 malloc(9) 而进入睡眠。Mbuf 头部的分配操作常常在对性能有严格要求的环境下被频繁执行， 因此实现代码必须小心地避免睡眠和长时间的操作。上述入口函数在 Mbuf 头部分配操作失败时将失败返回。

#### 6.7.2.7. `mpo_init_mount_label`

`void fsfuncmpo_init_mount_label(` | mntlabel, |
| fslabel`)`; |

`struct label *mntlabel`;
`struct label *fslabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mntlabel` | 将被初始化的mount 结构策略标记 |
`fslabel` | 将被初始化的文件系统策略标记 |

为一个新近实例化的 mount 点初始化标记。可以睡眠。

#### 6.7.2.8. `mpo_init_mount_fs_label`

`void fsfuncmpo_init_mount_fs_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的标记 |

为一个新近加载的文件系统初始化标记。可以睡眠。

#### 6.7.2.9. `mpo_init_pipe_label`

`void fsfuncmpo_init_pipe_label(` | label`)`; |

`struct label*label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填写的标记 |

为一个刚刚实例化的管道初始化安全标记。可以睡眠。

#### 6.7.2.10. `mpo_init_socket_label`

`void fsfuncmpo_init_socket_label(` | label, |
| flag`)`; |

`struct label *label`;
`int flag`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的新标记 |
`flag` | malloc(9) flags |

为一个刚刚实例化的套接字初始化安全标记。其中的 `flag` 域的值必须被指定为 M_WAITOK和M_NOWAIT之一，以避免在该初始化程中使用可能睡眠的malloc(9) 。

#### 6.7.2.11. `mpo_init_socket_peer_label`

`void fsfuncmpo_init_socket_peer_label(` | label, |
| flag`)`; |

`struct label *label`;
`int flag`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的新标记 |
`flag` | malloc(9) flags |

为刚刚实例化的套接字对等体进行标记的初始化。其中的 `flag` 域的值必须被指定为 M_WAITOK 和 M_NOWAIT 之一，以避免在该初始化程中使用可能睡眠的 malloc(9)。

#### 6.7.2.12. `mpo_init_proc_label`

`void fsfuncmpo_init_proc_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的新标记 |

为一个刚刚实例化的进程初始化安全标记。可以睡眠。

#### 6.7.2.13. `mpo_init_vnode_label`

`void fsfuncmpo_init_vnode_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被初始化的新标记 |

为一个刚刚实例化的 vnode 初始化安全标记。可以睡眠。

#### 6.7.2.14. `mpo_destroy_bpfdesc_label`

`void fsfuncmpo_destroy_bpfdesc_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | bpfdesc 标记 |

销毁一个 BPF 描述子上的标记。在该入口函数中，策略应当释放所有在内部分配与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.15. `mpo_destroy_cred_label`

`void fsfuncmpo_destroy_cred_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的标记 |

销毁一个信任状上的标记。在该入口函数中，策略应当释放所有在内部分配的与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.16. `mpo_destroy_devfsdirent_label`

`void fsfuncmpo_destroy_devfsdirent_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的标记 |

销毁一个 devfs 表项上的标记。在该入口函数中，策略应当释放所有在内部分配的与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.17. `mpo_destroy_ifnet_label`

`void fsfuncmpo_destroy_ifnet_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的标记 |

销毁与一个已删除接口相关联的标记。在该入口函数中，策略应当释放所有在内部分配的与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.18. `mpo_destroy_ipq_label`

`void fsfuncmpo_destroy_ipq_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的标记 |

销毁与一个 IP 分片队列相关联的标记。在该入口函数中，策略应当释放所有在内部分配的与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.19. `mpo_destroy_mbuf_label`

`void fsfuncmpo_destroy_mbuf_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的标记 |

销毁与一个 Mbuf 相关联的标记。在该入口函数中，策略应当释放所有在内部分配的与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.20. `mpo_destroy_mount_label`

`void fsfuncmpo_destroy_mount_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的 Mount 点标记 |

销毁与一个 mount 点相关联的标记。在该入口函数中，策略应当释放所有在内部分配的与 `mntlabel` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.21. `mpo_destroy_mount_label`

`void fsfuncmpo_destroy_mount_label(` | mntlabel, |
| fslabel`)`; |

`struct label *mntlabel`;
`struct label *fslabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mntlabel` | 将被销毁的 Mount 点标记 |
`fslabel` | File system label being destroyed> |

销毁与一个 mount 点相关联的标记。在该入口函数中，策略应当释放所有在内部分配的，与 `mntlabel` 和`fslabel` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.22. `mpo_destroy_socket_label`

`void fsfuncmpo_destroy_socket_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被销毁的套接字标记 |

销毁与一个套接字相关联的标记。在该入口函数中，策略应当释放所有在内部分配的，与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.23. `mpo_destroy_socket_peer_label`

`void fsfuncmpo_destroy_socket_peer_label(` | peerlabel`)`; |

`struct label *peerlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`peerlabel` | 将被销毁的套接字对等实体标记 |

销毁与一个套接字相关联的对等实体标记。在该入口函数中，策略应当释放所有在内部分配的，与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.24. `mpo_destroy_pipe_label`

`void fsfuncmpo_destroy_pipe_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 管道标记 |

销毁一个管道的标记。在该入口函数中，策略应当释放所有在内部分配的，与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.25. `mpo_destroy_proc_label`

`void fsfuncmpo_destroy_proc_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 进程标记 |

销毁一个进程的标记。在该入口函数中，策略应当释放所有在内部分配的，与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.26. `mpo_destroy_vnode_label`

`void fsfuncmpo_destroy_vnode_label(` | label`)`; |

`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 进程标记 |

销毁一个 vnode 的标记。在该入口函数中，策略应当释放所有在内部分配的，与 `label` 相关联的存储空间，以便销毁该标记。

#### 6.7.2.27. `mpo_copy_mbuf_label`

`void fsfuncmpo_copy_mbuf_label(` | src, |
| dest`)`; |

`struct label *src`;
`struct label *dest`;

参数 | 说明 | 锁定
--- | --- | ---
`src` | 源标记 |
`dest` | 目标标记 |

将 `src` 中的标记信息拷贝到 `dest`中。

#### 6.7.2.28. `mpo_copy_pipe_label`

`void fsfuncmpo_copy_pipe_label(` | src, |
| dest`)`; |

`struct label *src`;
`struct label *dest`;

参数 | 说明 | 锁定
--- | --- | ---
`src` | 源标记 |
`dest` | 目标标记 |

将 `src` 中的标记信息拷贝至 `dest`。

#### 6.7.2.29. `mpo_copy_vnode_label`

`void fsfuncmpo_copy_vnode_label(` | src, |
| dest`)`; |

`struct label *src`;
`struct label *dest`;

参数 | 说明 | 锁定
--- | --- | ---
`src` | 源标记 |
`dest` | 目标标记 |

将 `src` 中的标记信息拷贝至 `dest`。

#### 6.7.2.30. `mpo_externalize_cred_label`

`int fsfuncmpo_externalize_cred_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.31. `mpo_externalize_ifnet_label`

`int fsfuncmpo_externalize_ifnet_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.32. `mpo_externalize_pipe_label`

`int fsfuncmpo_externalize_pipe_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.33. `mpo_externalize_socket_label`

`int fsfuncmpo_externalize_socket_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.34. `mpo_externalize_socket_peer_label`

`int fsfuncmpo_externalize_socket_peer_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.35. `mpo_externalize_vnode_label`

`int fsfuncmpo_externalize_vnode_label(` | label, |
| element_name, |
| sb, |
| *claimed`)`; |

`struct label *label`;
`char *element_name`;
`struct sbuf *sb`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将用外部形式表示的标记 |
`element_name` | 需要外部表示标记的策略的名字 |
`sb` | 用来存放标记的文本表示形式的字符buffer |
`claimed` | 如果可以填充element_data 域，则其数值递增 |

根据传入的标记结构，产生一个以外部形式表示的标记。 一个外部形式标记，是标记内容的文本表示，它由用户级的应用程序使用，是用户可读的。 目前的MAC实现方案将依次调用策略的相应入口函数，因此， 具体策略的实现代码，需要在填写sb之前，先检查element_name中指定的名字。 如果element_name中的内容与你的策略名字不相符，则直接返回0。 仅当转换标记数据的过程中出现错误时，才返回非0值。 一旦策略决定填写element_data，递增*claim的数值。

#### 6.7.2.36. `mpo_internalize_cred_label`

`int fsfuncmpo_internalize_cred_label(` | label, |
| element_name, |
| element_data, |
| claimed`)`; |

`struct label *label`;
`char *element_name`;
`char *element_data`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填充的标记 |
`element_name` | 需要内部表示标记的策略的名字 |
`element_data` | 需要被转换的文本数据 |
`claimed` | 如果数据被正确转换，则其数值递增 |

根据一个文本形式的外部表示标记数据，创建一个内部形式的标记结构。 目前的MAC方案将依次调用所有策略的相关入口函数，来响应标记的内部转换请求， 因此，实现代码必须首先通过比较element_name中的内容和自己的策略名字， 来确定是否需要转换element_data中存放的数据。 类似的，如果名字不匹配或者数据转换操作成功，该函数返回0，并递增*claimed的值。

#### 6.7.2.37. `mpo_internalize_ifnet_label`

`int fsfuncmpo_internalize_ifnet_label(` | label, |
| element_name, |
| element_data, |
| claimed`)`; |

`struct label *label`;
`char *element_name`;
`char *element_data`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填充的标记 |
`element_name` | 需要内部表示标记的策略的名字 |
`element_data` | 需要被转换的文本数据 |
`claimed` | 如果数据被正确转换，则其数值递增 |

根据一个文本形式的外部表示标记数据，创建一个内部形式的标记结构。 目前的MAC方案将依次调用所有策略的相关入口函数，来响应标记的内部转换请求， 因此，实现代码必须首先通过比较element_name中的内容和自己的策略名字， 来确定是否需要转换element_data中存放的数据。 类似的，如果名字不匹配或者数据转换操作成功，该函数返回0，并递增*claimed的值。

#### 6.7.2.38. `mpo_internalize_pipe_label`

`int fsfuncmpo_internalize_pipe_label(` | label, |
| element_name, |
| element_data, |
| claimed`)`; |

`struct label *label`;
`char *element_name`;
`char *element_data`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填充的标记 |
`element_name` | 需要内部表示标记的策略的名字 |
`element_data` | 需要被转换的文本数据 |
`claimed` | 如果数据被正确转换，则其数值递增 |

根据一个文本形式的外部表示标记数据，创建一个内部形式的标记结构。 目前的MAC方案将依次调用所有策略的相关入口函数，来响应标记的内部转换请求， 因此，实现代码必须首先通过比较element_name中的内容和自己的策略名字， 来确定是否需要转换element_data中存放的数据。 类似的，如果名字不匹配或者数据转换操作成功，该函数返回0，并递增*claimed的值。

#### 6.7.2.39. `mpo_internalize_socket_label`

`int fsfuncmpo_internalize_socket_label(` | label, |
| element_name, |
| element_data, |
| claimed`)`; |

`struct label *label`;
`char *element_name`;
`char *element_data`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填充的标记 |
`element_name` | 需要内部表示标记的策略的名字 |
`element_data` | 需要被转换的文本数据 |
`claimed` | 如果数据被正确转换，则其数值递增 |

根据一个文本形式的外部表示标记数据，创建一个内部形式的标记结构。 目前的MAC方案将依次调用所有策略的相关入口函数，来响应标记的内部转换请求， 因此，实现代码必须首先通过比较element_name中的内容和自己的策略名字， 来确定是否需要转换element_data中存放的数据。 类似的，如果名字不匹配或者数据转换操作成功，该函数返回0，并递增*claimed的值。

#### 6.7.2.40. `mpo_internalize_vnode_label`

`int fsfuncmpo_internalize_vnode_label(` | label, |
| element_name, |
| element_data, |
| claimed`)`; |

`struct label *label`;
`char *element_name`;
`char *element_data`;
`int *claimed`;

参数 | 说明 | 锁定
--- | --- | ---
`label` | 将被填充的标记 |
`element_name` | 需要内部表示标记的策略的名字 |
`element_data` | 需要被转换的文本数据 |
`claimed` | 如果数据被正确转换，则其数值递增 |

根据一个文本形式的外部表示标记数据，创建一个内部形式的标记结构。 目前的MAC方案将依次调用所有策略的相关入口函数，来响应标记的内部转换请求， 因此，实现代码必须首先通过比较element_name中的内容和自己的策略名字， 来确定是否需要转换element_data中存放的数据。 类似的，如果名字不匹配或者数据转换操作成功，该函数返回0，并递增*claimed的值。

### 6.7.3. 标记事件

策略模块使用MAC 框架提供的“标记事件”类入口函数，对内核对象的标记进行操作。策略模块将感兴趣的被标记内核对象的相关生命周期事件 注册在恰当的入口点上。对象的初始化、创建和销毁事件均提供了钩子点。在某些对象上还可以实现重新标记，即，允许用户进程改变对象上的标记值。 对某些对象可以实现其特定的对象事件，比如与 IP 重组相关的标记事件。一个典型的被标记对象在其生命周期中将拥有下列入口函数：

标记初始化 o （对象相关的等待） \ 标记创建 o \ 重新标记事件， o--<--. 各种对象相关的， | | 访问控制事件 ~-->--o \ 标记销毁 o

使用标记初始化入口函数，策略可以以一种统一的、与对象使用环境无关的方式设置标记的初始值。 分配给一个策略的缺省 slot 值为0，这样不使用标记的策略可能并不需要执行专门的初始化操作。

标记的创建事件发生在将一个内核数据结构同一个真实的内核对象相关联（内核对象实例化）的时刻。 例如，在真正被使用之前，在一个缓冲池内已分配的 mbuf 数据结构，将保持为“未使用”状态。 因此，mbuf 的分配操作将导致针对该 mbuf 的标记初始化操作，而 mbuf 的创建操作则被推迟到该 mbuf 真正与一个数据报相关联的时刻。 通常，调用者将会提供创建事件的上下文，包括创建环境、创建过程中涉及的其他对象的标记等。例如，当一个套接字创建一个 mbuf 时， 除了新创建的 mbuf 及其标记之外，作为创建者的套接字与其标记也被提交给策略检查。 不提倡在创建对象时就为其分配内存的原因有两个：创建操作可能发生在对性能有严格要求的内核接口上； 而且，因为创建调用不允许失败，所以无法报告内存分配失败。

对象特有的事件一般不会引发其他的标记事件，但是在对象上下文发生改变时，策略使用它们可以对相关标记进行修改或更新操作。 例如，在MAC_UPDATE_IPQ 入口函数之内，某个 IP 分片重组队列的标记可能会因为队列中接收了新的 mbuf 而被更新。

访问控制事件将在后续章节中详细讨论。

策略通过执行标记销毁操作，释放为其分配的存储空间或维护的状态，之后内核才可以重用或者释放对象的内核数据结构。

除了与特定内核对象绑定的普通标记之外，还有一种额外的标记类型：临时标记。这些标记用于存放由用户进程提交的更新信息。 它们的初始化和销毁操作与其他标记一样，只是创建事件，MAC_INTERNALIZE，略有不同： 该函数接受用户提交的标记，负责将其转化为内核表示形式。

#### 6.7.3.1. 文件系统对象标记事件操作

##### 6.7.3.1.1. `mpo_associate_vnode_devfs`

`void fsfuncmpo_associate_vnode_devfs(` | mp, |
| fslabel, |
| de, |
| delabel, |
| vp, |
| vlabel`)`; |

`struct mount *mp`;
`struct label *fslabel`;
`struct devfs_dirent *de`;
`struct label *delabel`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mp` | Devfs 挂载点 |
`fslabel` | Devfs 文件系统标记 (`mp->mnt_fslabel`) |
`de` | Devfs 目录项 |
`delabel` | 与 `de` 相关联的策略标记 |
`vp` | 与 `de` 相关联的 vnode |
`vlabel` | 与 `vp` 相关联的策略标记 |

根据参数 `de` 传入的 devfs 目录项及其标记信息，为一个新近创建的 devfs vnode 填充标记（`vlabel`）。

##### 6.7.3.1.2. `mpo_associate_vnode_extattr`

`int fsfuncmpo_associate_vnode_extattr(` | mp, |
| fslabel, |
| vp, |
| vlabel`)`; |

`struct mount *mp`;
`struct label *fslabel`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mp` | 文件系统挂载点 |
`fslabel` | 文件系统标记 |
`vp` | 将被标记的 vnode |
`vlabel` | 与 `vp` 相关联的策略标记 |

从文件系统扩展属性中读取 `vp` 的标记。成功，返回 `0`。 不成功，则在 `errno` 指定的相应的错误编码。 如果文件系统不支持扩展属性的读取操作，则可以考虑将 `fslabel` 拷贝至 `vlabel`。

##### 6.7.3.1.3. `mpo_associate_vnode_singlelabel`

`void fsfuncmpo_associate_vnode_singlelabel(` | mp, |
| fslabel, |
| vp, |
| vlabel`)`; |

`struct mount *mp`;
`struct label *fslabel`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mp` | 文件系统挂载点 |
`fslabel` | 文件系统标记 |
`vp` | 将被标记的 vnode |
`vlabel` | 与 `vp` 相关联的策略标记 |

在非多重标记文件系统上，使用该入口函数，根据文件系统标记，`fslabel`， 为 `vp` 设置策略标记。

##### 6.7.3.1.4. `mpo_create_devfs_device`

`void fsfuncmpo_create_devfs_device(` | dev, |
| devfs_dirent, |
| label`)`; |

`dev_t dev`;
`struct devfs_dirent *devfs_dirent`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`dev` | `devfs_dirent` 对应的设备 |
`devfs_dirent` | 将被标记的 Devfs 目录项 |
`label` | 将被填写的 `devfs_dirent` 标记 |

为传入设备新建的 devfs_dirent 填写标记。该函数将在设备文件系统加载、重构或添加新设备时被调用。

##### 6.7.3.1.5. `mpo_create_devfs_directory`

`void fsfuncmpo_create_devfs_directory(` | dirname, |
| dirnamelen, |
| devfs_dirent, |
| label`)`; |

`char *dirname`;
`int dirnamelen`;
`struct devfs_dirent *devfs_dirent`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`dirname` | 新建目录的名字 |
`namelen` | 字符串 `dirname` 的长度 |
`devfs_dirent` | 新建目录在 Devfs 中对应的目录项 |

为传入目录参数的新建 devfs_dirent 填写标记。该函数将在加载、重构设备文件系统，或者添加一个需要指定目录结构的新设备时被调用。

##### 6.7.3.1.6. `mpo_create_devfs_symlink`

`void fsfuncmpo_create_devfs_symlink(` | cred, |
| mp, |
| dd, |
| ddlabel, |
| de, |
| delabel`)`; |

`struct ucred *cred`;
`struct mount *mp`;
`struct devfs_dirent *dd`;
`struct label *ddlabel`;
`struct devfs_dirent *de`;
`struct label *delabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`mp` | devfs 挂载点 |
`dd` | 链接目标 |
`ddlabel` | 与 `dd` 相关联的标记 |
`de` | 符号链接项 |
`delabel` | 与 `de` 相关联的策略标记 |

为新近创建的 devfs(5) 符号链接项填写标记（`delabel`）。

##### 6.7.3.1.7. `mpo_create_vnode_extattr`

`int fsfuncmpo_create_vnode_extattr(` | cred, |
| mp, |
| fslabel, |
| dvp, |
| dlabel, |
| vp, |
| vlabel, |
| cnp`)`; |

`struct ucred *cred`;
`struct mount *mp`;
`struct label *fslabel`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct vnode *vp`;
`struct label *vlabel`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`mount` | 文件系统挂载点 |
`label` | 文件系统标记 |
`dvp` | 父目录 vnode |
`dlabel` | 与 `dvp` 相关联的策略标记 |
`vp` | 新创建的 vnode |
`vlabel` | 与 `vp` 相关联的策略标记 |
`cnp` | `vp`中的子域名字 |

将 `vp` 的标记写入文件扩展属性。成功，将标记填入 `vlabel`， 并返回 0。否则，返回对应的错误编码。

##### 6.7.3.1.8. `mpo_create_mount`

`void fsfuncmpo_create_mount(` | cred, |
| mp, |
| mnt, |
| fslabel`)`; |

`struct ucred *cred`;
`struct mount *mp`;
`struct label *mnt`;
`struct label *fslabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`mp` | 客体；将被挂载的文件系统 |
`mntlabel` | 将被填写的 `mp` 的策略标记 |
`fslabel` | 将被挂载到 `mp` 的文件系统的策略标记。 |

为传入的主体信任状所创建的挂载点填写标记。该函数将在文件系统挂载时被调用。

##### 6.7.3.1.9. `mpo_create_root_mount`

`void fsfuncmpo_create_root_mount(` | cred, |
| mp, |
| mntlabel, |
| fslabel`)`; |

`struct ucred *cred`;
`struct mount *mp`;
`struct label *mntlabel`;
`struct label *fslabel`;

参数 | 说明 | 锁定
--- | --- | ---
见 第 6.7.3.1.8 节 “`mpo_create_mount`”.

为传入的主体信任状所创建的挂载点填写标记。该函数将在挂载根文件系统时，mpo_create_mount; 之后被调用。

##### 6.7.3.1.10. `mpo_relabel_vnode`

`void fsfuncmpo_relabel_vnode(` | cred, |
| vp, |
| vnodelabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *vnodelabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 将被重新标记的 vnode |
`vnodelabel` | `vp` 现有的策略标记 |
`newlabel` | 将取代`vnodelabel`的新（可能只是部分）标记 |

根据传入的新标记和主体信任状，更新参数 vnode 的标记。

##### 6.7.3.1.11. `mpo_setlabel_vnode_extattr`

`int fsfuncmpo_setlabel_vnode_extattr(` | cred, |
| vp, |
| vlabel, |
| intlabel`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *vlabel`;
`struct label *intlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 写出标记所对应的 vnode |
`vlabel` | `vp`的策略标记 |
`intlabel` | 将被写入磁盘的标记 |

将参数 `intlabel` 给出的标记信息写入指定 vnode 的扩展属性。 该函数被 `vop_stdcreatevnode_ea` 所调用。

##### 6.7.3.1.12. `mpo_update_devfsdirent`

`void fsfuncmpo_update_devfsdirent(` | devfs_dirent, |
| direntlabel, |
| vp, |
| vnodelabel`)`; |

`struct devfs_dirent *devfs_dirent`;
`struct label *direntlabel`;
`struct vnode *vp`;
`struct label *vnodelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`devfs_dirent` | 客体；devfs 目录项 |
`direntlabel` | 将被更新的`devfs_dirent`的策略标记 |
`vp` | 父 vnode | 已锁定
`vnodelabel` | `vp`的策略标记 |

根据所传入的 devfs vnode 标记，对 `devfs_dirent` 的标记进行更新。 重新标记一个 devfs vnode 的操作成功之后，将调用该函数来确认标记的改变，如此，即使相应的 vnode 数据结构被内核回收重用， 也不会丢失标记的新状态。另外，在 devfs 中新建一个符号链接时，紧接着`mac_vnode_create_from_vnode`， 也将调用该函数，对 vnode 标记进行初始化操作。

#### 6.7.3.2. IPC 对象标记事件操作

##### 6.7.3.2.1. `mpo_create_mbuf_from_socket`

`void fsfuncmpo_create_mbuf_from_socket(` | so, |
| socketlabel, |
| m, |
| mbuflabel`)`; |

`struct socket *so`;
`struct label *socketlabel`;
`struct mbuf *m`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`socket` | 套接字 | 套接字锁定 WIP
`socketlabel` | `socket` 的策略标记 |
`m` | 客体；mbuf |
`mbuflabel` | 将被填写的 `m` 的策略标记 |

根据传入的套接字标记为新创建的mbuf头部设置标记。 每当套接字产生一个新的数据报或者消息，并将其存储在参数 mbuf 中时，将调用该函数。

##### 6.7.3.2.2. `mpo_create_pipe`

`void fsfuncmpo_create_pipe(` | cred, |
| pipe, |
| pipelabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe` 的策略标记 |

根据传入的主体信任状参数，设置新建管道的标记。每当一个新管道被创建，该函数将被调用。

##### 6.7.3.2.3. `mpo_create_socket`

`void fsfuncmpo_create_socket(` | cred, |
| so, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *so`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`so` | 客体；将被标记的套接字 |
`socketlabel` | 将被填写的 `so` 的标记 |

根据传入的主体信任状参数，设置新建套接字的标记。每当新建一个套接字，该函数将被调用。

##### 6.7.3.2.4. `mpo_create_socket_from_socket`

`void fsfuncmpo_create_socket_from_socket(` | oldsocket, |
| oldsocketlabel, |
| newsocket, |
| newsocketlabel`)`; |

`struct socket *oldsocket`;
`struct label *oldsocketlabel`;
`struct socket *newsocket`;
`struct label *newsocketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`oldsocket` | 监听套接字 |
`oldsocketlabel` | `oldsocket` 的策略标记 |
`newsocket` | 新建套接字 |
`newsocketlabel` | `newsocket` 的策略标记 |

根据 listen(2) 套接字 `oldsocket`， 为新建 accept(2) 的套接字 `newsocket`，设置标记。

##### 6.7.3.2.5. `mpo_relabel_pipe`

`void fsfuncmpo_relabel_pipe(` | cred, |
| pipe, |
| oldlabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *oldlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`oldlabel` | `pipe` 的当前策略标记 |
`newlabel` | 将为`pipe` 设置的新的策略标记 |

为`pipe`设置新标记`newlabel`。

##### 6.7.3.2.6. `mpo_relabel_socket`

`void fsfuncmpo_relabel_socket(` | cred, |
| so, |
| oldlabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct socket *so`;
`struct label *oldlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`so` | 客体；套接字 |
`oldlabel` | `so` 的当前标记 |
`newlabel` | 将为`socket` 设置的新标记 |

根据传入的标记参数，对套接字的当前标记进行更新。

##### 6.7.3.2.7. `mpo_set_socket_peer_from_mbuf`

`void fsfuncmpo_set_socket_peer_from_mbuf(` | mbuf, |
| mbuflabel, |
| oldlabel, |
| newlabel`)`; |

`struct mbuf *mbuf`;
`struct label *mbuflabel`;
`struct label *oldlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mbuf` | 从套接字接收到的第一个数据报 |
`mbuflabel` | `mbuf` 的标记 |
`oldlabel` | 套接字的当前标记 |
`newlabel` | 将为套接字填写的策略标记 |

根据传入的 mbuf 标记，设置某个 stream 套接字的对等标志。 除Unix域的套接字之外，每当一个 stream 套接字接收到第一个数据报时，该函数将被调用。

##### 6.7.3.2.8. `mpo_set_socket_peer_from_socket`

`void fsfuncmpo_set_socket_peer_from_socket(` | oldsocket, |
| oldsocketlabel, |
| newsocket, |
| newsocketpeerlabel`)`; |

`struct socket *oldsocket`;
`struct label *oldsocketlabel`;
`struct socket *newsocket`;
`struct label *newsocketpeerlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`oldsocket` | 本地套接字 |
`oldsocketlabel` | `oldsocket` 的策略标记 |
`newsocket` | 对等套接字 |
`newsocketpeerlabel` | 将为`newsocket`填写的策略标记 |

根据传入的远程套接字端点，为一个 stream UNIX 与套接字设置对等标记。 每当相应的套接字对之间进行连接时，该函数将在两端分别被调用。

#### 6.7.3.3. Network Object Labeling Event Operations

##### 6.7.3.3.1. `mpo_create_bpfdesc`

`void fsfuncmpo_create_bpfdesc(` | cred, |
| bpf_d, |
| bpflabel`)`; |

`struct ucred *cred`;
`struct bpf_d *bpf_d`;
`struct label *bpflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`bpf_d` | 客体；bpf 描述子 |
`bpf` | 将为`bpf_d`填写的策略标记 |

根据传入的主体信任状参数，为新建的 BPF 描述子设置标记。 当进程打开 BPF 设备节点时，该函数将被调用。

##### 6.7.3.3.2. `mpo_create_ifnet`

`void fsfuncmpo_create_ifnet(` | ifnet, |
| ifnetlabel`)`; |

`struct ifnet *ifnet`;
`struct label *ifnetlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`ifnet` | 网络接口 |
`ifnetlabel` | 将为`ifnet`填写的策略标记 |

为新建的网络接口设置标记。该函数在以下情况下被调用： 当一个新的物理接口变为可用时，或者当一个伪接口在引导时或由于某个用户操作而实例化时。

##### 6.7.3.3.3. `mpo_create_ipq`

`void fsfuncmpo_create_ipq(` | fragment, |
| fragmentlabel, |
| ipq, |
| ipqlabel`)`; |

`struct mbuf *fragment`;
`struct label *fragmentlabel`;
`struct ipq *ipq`;
`struct label *ipqlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`fragment` | 第一个被接收的 IP 分片 |
`fragmentlabel` | `fragment` 的策略标记 |
`ipq` | 将被标记的 IP 重组队列 |
`ipqlabel` | 将为`ipq`填写的策略标记 |

根据第一个接收到的分片的 mbuf 头部信息，为新建的 IP 分片重组队列设置标记。

##### 6.7.3.3.4. `mpo_create_datagram_from_ipq`

`void fsfuncmpo_create_create_datagram_from_ipq(` | ipq, |
| ipqlabel, |
| datagram, |
| datagramlabel`)`; |

`struct ipq *ipq`;
`struct label *ipqlabel`;
`struct mbuf *datagram`;
`struct label *datagramlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`ipq` | IP 重组队列 |
`ipqlabel` | `ipq` 的策略标记 |
`datagram` | 将被标记的数据报 |
`datagramlabel` | 将为`datagramlabel`填写的策略标记 |

根据 IP 分片重组队列，为刚刚重组完毕的 IP 数据报设置标记。

##### 6.7.3.3.5. `mpo_create_fragment`

`void fsfuncmpo_create_fragment(` | datagram, |
| datagramlabel, |
| fragment, |
| fragmentlabel`)`; |

`struct mbuf *datagram`;
`struct label *datagramlabel`;
`struct mbuf *fragment`;
`struct label *fragmentlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`datagram` | 数据报 |
`datagramlabel` | `datagram` 的策略标记 |
`fragment` | 将被标记的分片 |
`fragmentlabel` | 将为`datagram`填写的策略标记 |

根据数据报所对应的 mbuf 头部信息，为其新建的分片的 mbuf 头部设置标记。

##### 6.7.3.3.6. `mpo_create_mbuf_from_mbuf`

`void fsfuncmpo_create_mbuf_from_mbuf(` | oldmbuf, |
| oldmbuflabel, |
| newmbuf, |
| newmbuflabel`)`; |

`struct mbuf *oldmbuf`;
`struct label *oldmbuflabel`;
`struct mbuf *newmbuf`;
`struct label *newmbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`oldmbuf` | 已有的（源）mbuf |
`oldmbuflabel` | `oldmbuf` 的策略标记 |
`newmbuf` | 将被标记的新建 mbuf |
`newmbuflabel` | 将为`newmbuf`填写的策略标记 |

根据某个现有数据报的 mbuf 头部信息，为新建数据报的 mbuf 头部设置标记。在许多条件下将会调用该函数， 比如，由于对齐要求而重新分配某个 mbuf 时。

##### 6.7.3.3.7. `mpo_create_mbuf_linklayer`

`void fsfuncmpo_create_mbuf_linklayer(` | ifnet, |
| ifnetlabel, |
| mbuf, |
| mbuflabel`)`; |

`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct mbuf *mbuf`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`ifnet` | 网络接口 |
`ifnetlabel` | `ifnet` 的策略标记 |
`mbuf` | 新建数据报的 mbuf 头部 |
`mbuflabel` | 将为`mbuf`填写的策略标记 |

为在给定接口上由于某个链路层响应而新建的数据报的mbuf头部设置标记。 该函数将在若干条件下被调用，比如当IPv4和IPv6协议栈在响应ARP或者ND6时。

##### 6.7.3.3.8. `mpo_create_mbuf_from_bpfdesc`

`void fsfuncmpo_create_mbuf_from_bpfdesc(` | bpf_d, |
| bpflabel, |
| mbuf, |
| mbuflabel`)`; |

`struct bpf_d *bpf_d`;
`struct label *bpflabel`;
`struct mbuf *mbuf`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`bpf_d` | BPF 描述子 |
`bpflabel` | `bpflabel` 的策略标记 |
`mbuf` | 将被标记的新建 mbuf |
`mbuflabel` | 将为`mbuf`填写的策略标记 |

为使用参数 BPF 描述子创建的新数据报的 mbuf 头部设置标记。 当对参数 BPF 描述子所关联的 BPF 设备进行写操作时，该函数将被调用。

##### 6.7.3.3.9. `mpo_create_mbuf_from_ifnet`

`void fsfuncmpo_create_mbuf_from_ifnet(` | ifnet, |
| ifnetlabel, |
| mbuf, |
| mbuflabel`)`; |

`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct mbuf *mbuf`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`ifnet` | 网络接口 |
`ifnetlabel` | `ifnetlabel` 的策略标记 |
`mbuf` | 新建数据报的 mbuf 头部 |
`mbuflabel` | 将为`mbuf`填写的策略标记 |

为从网络接口参数创建的数据报的 mbuf 头部设置标记。

##### 6.7.3.3.10. `mpo_create_mbuf_multicast_encap`

`void fsfuncmpo_create_mbuf_multicast_encap(` | oldmbuf, |
| oldmbuflabel, |
| ifnet, |
| ifnetlabel, |
| newmbuf, |
| newmbuflabel`)`; |

`struct mbuf *oldmbuf`;
`struct label *oldmbuflabel`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct mbuf *newmbuf`;
`struct label *newmbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`oldmbuf` | 现有数据报的 mbuf 头部 |
`oldmbuflabel` | `oldmbuf` 的策略标记 |
`ifnet` | 网络接口 |
`ifnetlabel` | `ifnet` 的策略标记 |
`newmbuf` | 将被标记的新建数据报 mbuf 头部 |
`newmbuflabel` | 将为`newmbuf`填写的策略标记 |

当传入的已有数据报被给定多播封装接口（multicast encapsulation interface）处理时被调用， 为新创建的数据报所在 mbuf 头部设置标记。 每当使用该虚拟接口传递一个mbuf时，将调用该函数。

##### 6.7.3.3.11. `mpo_create_mbuf_netlayer`

`void fsfuncmpo_create_mbuf_netlayer(` | oldmbuf, |
| oldmbuflabel, |
| newmbuf, |
| newmbuflabel`)`; |

`struct mbuf *oldmbuf`;
`struct label *oldmbuflabel`;
`struct mbuf *newmbuf`;
`struct label *newmbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`oldmbuf` | 接收的数据报 |
`oldmbuflabel` | `oldmbuf` 的策略标记 |
`newmbuf` | 新建数据报 |
`newmbuflabel` | `newmbuf` 的策略标记 |

为由 IP 堆栈因为响应接收数据报（`oldmbuf`）而新建的数据报设置其 mbuf 头部的标记。 许多情况下需要调用该函数，比如，响应 ICMP 请求数据报时。

##### 6.7.3.3.12. `mpo_fragment_match`

`int fsfuncmpo_fragment_match(` | fragment, |
| fragmentlabel, |
| ipq, |
| ipqlabel`)`; |

`struct mbuf *fragment`;
`struct label *fragmentlabel`;
`struct ipq *ipq`;
`struct label *ipqlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`fragment` | IP 数据报分片 |
`fragmentlabel` | `fragment` 的策略标记 |
`ipq` | IP 分片重组队列 |
`ipqlabel` | `ipq` 的策略标记 |

根据所传入的 IP 分片重组队列（`ipq`）的标记， 检查包含一个 IP 数据报（`fragment`）的 mbuf 的头部是否符合其要求。 符合，则返回1。否则，返回0。 每当 IP 堆栈尝试将一个刚刚接收到的分片放入某个已有的分片重组队列中时，将调用该函数进行安全检查； 如果失败，将为分片重新实例化一个新的分片重组队列。 策略可以利用该入口函数，根据标记或者其他信息阻止不期望的 IP 分片重组。

##### 6.7.3.3.13. `mpo_relabel_ifnet`

`void fsfuncmpo_relabel_ifnet(` | cred, |
| ifnet, |
| ifnetlabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`ifnet` | 客体；网络接口 |
`ifnetlabel` | `ifnet` 的策略标记 |
`newlabel` | 将为`ifnet`设置的新标记 |

根据所传入的新标记，`newlabel`，以及主体信任状， `cred`，对网络接口的标记进行更新。

##### 6.7.3.3.14. `mpo_update_ipq`

`void fsfuncmpo_update_ipq(` | fragment, |
| fragmentlabel, |
| ipq, |
| ipqlabel`)`; |

`struct mbuf *fragment`;
`struct label *fragmentlabel`;
`struct ipq *ipq`;
`struct label *ipqlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`mbuf` | IP 分片 |
`mbuflabel` | `mbuf` 的策略标记 |
`ipq` | IP 分片重组队列 |
`ipqlabel` | 将被更新的`ipq`的当前策略标记 |

根据所传入的 IP 分片 mbuf 头部（`mbuf`）为接收 它的 IP 分片重组队列（`ipq`）的标记进行更新。

#### 6.7.3.4. 进程标记事件操作

##### 6.7.3.4.1. `mpo_create_cred`

`void fsfuncmpo_create_cred(` | parent_cred, |
| child_cred`)`; |

`struct ucred *parent_cred`;
`struct ucred *child_cred`;

参数 | 说明 | 锁定
--- | --- | ---
`parent_cred` | 父主体信任状 |
`child_cred` | 子主体信任状 |

根据所传入的主体信任状，为新建的主体信任状设置标记。 每当为一个新建的 struct ucred调用 crcopy(9) 时，将调用此函数。 该函数不应与进程复制（forking）或者创建事件混为一谈。

##### 6.7.3.4.2. `mpo_execve_transition`

`void fsfuncmpo_execve_transition(` | old, |
| new, |
| vp, |
| vnodelabel`)`; |

`struct ucred *old`;
`struct ucred *new`;
`struct vnode *vp`;
`struct label *vnodelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`old` | 已有的主体信任状 | 不可改变
`new` | 将被标记的新主体信任状 |
`vp` | 将被执行的文件 | 已被锁定
`vnodelabel` | `vp` 的策略标记 |

一个拥有信任状`old`的主体由于执行(`vp`文件而导致标记转换时， 该函数根据vnode标记为该主体重新标记为`new`。 每当一个进程请求执行vnode文件，而通过 入口函数`mpo_execve_will_transition` 有成功返回的策略时，将调用该函数。 策略模块可以通过传入两个主体信任状和简单地调用 `mpo_create_cred` 来实现该入口函数， so as not to implement a transitioning event. 一旦策略实现了`mpo_create_cred`函数，即使没有实现 `mpo_execve_will_transition`，也应该实现该函数。

##### 6.7.3.4.3. `mpo_execve_will_transition`

`int fsfuncmpo_execve_will_transition(` | old, |
| vp, |
| vnodelabel`)`; |

`struct ucred *old`;
`struct vnode *vp`;
`struct label *vnodelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`old` | 在执行execve(2)之前的主体信任状 | 不可改变
`vp` | 将被执行的文件 |
`vnodelabel` | `vp` 的策略标记 |

由策略决定，当参数主体信任状执行参数 vnode 时，是否需要进行一个标记转换操作。如果需要，返回1； 否则，返回0。即使一个策略返回0，它也必须为自己不期望的对 `mpo_execve_transition`的调用作好准备，因为只要有其他任何一个策略要求转换，就将执行此函数。

##### 6.7.3.4.4. `mpo_create_proc0`

`void fsfuncmpo_create_proc0(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 将被填写的主体信任状 |

为进程0，所有内核进程的祖先，创建主体信任状。

##### 6.7.3.4.5. `mpo_create_proc1`

`void fsfuncmpo_create_proc1(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 将被填写的主体信任状 |

为进程1，所有用户进程的祖先，创建主体信任状。

##### 6.7.3.4.6. `mpo_relabel_cred`

`void fsfuncmpo_relabel_cred(` | cred, |
| newlabel`)`; |

`struct ucred *cred`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`newlabel` | 将被应用到 `cred` 上的新标记 |

根据传入的新标记，对主体信任状上的标记进行更新。

### 6.7.4. 访问控制检查

通过访问控制入口函数，策略模块能影响内核的访问控制决策。 通常情况下，不是绝对，一个访问控制入口函数的参数有，一个或者若干个授权信任状，和相关操作涉及的其他任何对象的信息（其中可能包含标记）。 访问控制入口函数返回0，表示允许该操作；否则，返回一个 errno(2) 错误编码。调用该入口函数，将遍历所有系统注册的策略模块，逐一进行 策略相关的检查和决策，之后按照下述方法组合不同策略的返回结果：只有当所有的模块均允许该操作时，才成功返回。 否则，如果有一个或者若干模块失败返回，则整个检查不通过。如果有多个模块的检查出错返回，将由定义在`kern_mac.c` 中的 `error_select()` 函数从它们返回的错误编码中，选择一个合适的，返回给用户。

最高优先级 | EDEADLK
| EINVAL
| ESRCH
| EACCES
最低优先级 | EPERM

如果所有策略模块返回的错误编码均没有出现在上述优先级序列表中，则任意选择一个返回。 选择错误编码的一般次序为：内核错误，无效的参数，对象不存在，访问被拒绝，和其他错误。

#### 6.7.4.1. `mpo_check_bpfdesc_receive`

`int fsfuncmpo_check_bpfdesc_receive(` | bpf_d, |
| bpflabel, |
| ifnet, |
| ifnetlabel`)`; |

`struct bpf_d *bpf_d`;
`struct label *bpflabel`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`bpf_d` | 主体；BPF 描述子 |
`bpflabel` | `bpf_d` 的策略标记 |
`ifnet` | 客体；网络接口 |
`ifnetlabel` | `ifnet` 的策略标记 |

决定 MAC 框架是否应该允许将由参数接口接收到的数据报传递给由 BPF 描述子所对应的缓冲区。成功，则返回0； 否则，返回错误编码信息`errno`。建议使用的错误编码有：EACCES，用于标记不符的情况； EPERM，用于缺少特权的情况。

#### 6.7.4.2. `mpo_check_kenv_dump`

`int fsfuncmpo_check_kenv_dump(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |

决定相关主体是否应该被允许查询内核环境状态（参考 kenv(2)）。

#### 6.7.4.3. `mpo_check_kenv_get`

`int fsfuncmpo_check_kenv_get(` | cred, |
| name`)`; |

`struct ucred *cred`;
`char *name`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`name` | 内核的环境变量名字 |

决定相关主体是否可以查询内核中给定环境变量的状态。

#### 6.7.4.4. `mpo_check_kenv_set`

`int fsfuncmpo_check_kenv_set(` | cred, |
| name`)`; |

`struct ucred *cred`;
`char *name`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`name` | 内核的环境变量名字 |

决定相关主体是否有权设置给定内核环境变量的值。

#### 6.7.4.5. `mpo_check_kenv_unset`

`int fsfuncmpo_check_kenv_unset(` | cred, |
| name`)`; |

`struct ucred *cred`;
`char *name`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`name` | 内核的环境变量名字Kernel environment variable name |

决定相关主体是否有权清除给定的内核环境变量的设置。

#### 6.7.4.6. `mpo_check_kld_load`

`int fsfuncmpo_check_kld_load(` | cred, |
| vp, |
| vlabel`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 内核模块的 vnode |
`vlabel` | `vp`的策略标记 |

决定相关主体是否有权加载给定的模块文件。

#### 6.7.4.7. `mpo_check_kld_stat`

`int fsfuncmpo_check_kld_stat(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |

决定相关主体是否有权访问内核的加载模块文件链表以及相关的统计数据。

#### 6.7.4.8. `mpo_check_kld_unload`

`int fsfuncmpo_check_kld_unload(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |

决定相关主体是否有权卸载一个内核模块。

#### 6.7.4.9. `mpo_check_pipe_ioctl`

`int fsfuncmpo_check_pipe_ioctl(` | cred, |
| pipe, |
| pipelabel, |
| cmd, |
| data`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;
`unsigned long cmd`;
`void *data`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的策略标记 |
`cmd` | ioctl(2) 命令 |
`data` | ioctl(2) 数据 |

决定相关主体是否有权调用指定的 ioctl(2) 系统调用。

#### 6.7.4.10. `mpo_check_pipe_poll`

`int fsfuncmpo_check_pipe_poll(` | cred, |
| pipe, |
| pipelabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的策略标记 |

决定相关主体是否有权对管道`pipe`执行poll操作。

#### 6.7.4.11. `mpo_check_pipe_read`

`int fsfuncmpo_check_pipe_read(` | cred, |
| pipe, |
| pipelabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的策略标记 |

决定该主体是否有权读取`pipe`。

#### 6.7.4.12. `mpo_check_pipe_relabel`

`int fsfuncmpo_check_pipe_relabel(` | cred, |
| pipe, |
| pipelabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的当前策略标记 |
`newlabel` | 将为`pipelabel`设置的新标记 |

决定该主体是否有权为`pipe`重新设置标记。

#### 6.7.4.13. `mpo_check_pipe_stat`

`int fsfuncmpo_check_pipe_stat(` | cred, |
| pipe, |
| pipelabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的策略标记 |

决定该主体是否有权查询与`pipe`相关的统计信息。

#### 6.7.4.14. `mpo_check_pipe_write`

`int fsfuncmpo_check_pipe_write(` | cred, |
| pipe, |
| pipelabel`)`; |

`struct ucred *cred`;
`struct pipe *pipe`;
`struct label *pipelabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`pipe` | 管道 |
`pipelabel` | `pipe`的策略标记 |

决定该主体是否有权写`pipe`。

#### 6.7.4.15. `mpo_check_socket_bind`

`int fsfuncmpo_check_socket_bind(` | cred, |
| socket, |
| socketlabel, |
| sockaddr`)`; |

`struct ucred *cred`;
`struct socket *socket`;
`struct label *socketlabel`;
`struct sockaddr *sockaddr`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`socket` | 将被绑定的套接字 |
`socketlabel` | `socket`的策略标记 |
`sockaddr` | `socket`的地址 |

#### 6.7.4.16. `mpo_check_socket_connect`

`int fsfuncmpo_check_socket_connect(` | cred, |
| socket, |
| socketlabel, |
| sockaddr`)`; |

`struct ucred *cred`;
`struct socket *socket`;
`struct label *socketlabel`;
`struct sockaddr *sockaddr`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`socket` | 将被连接的套接字 |
`socketlabel` | `socket`的策略标记 |
`sockaddr` | `socket`的地址 |

决定该主体（`cred`）是否有权将套接字（`socket`）绑定到地址 `sockaddr`。成功，返回0，否则返回一个错误编码`errno`。 建议采用的错误编码有：EACCES，用于标记不符的情况；EPERM，用于特权不足的情况。

#### 6.7.4.17. `mpo_check_socket_receive`

`int fsfuncmpo_check_socket_receive(` | cred, |
| so, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *so`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`so` | 套接字 |
`socketlabel` | `so`的策略标记 |

决定该主体是否有权查询套接字`so`的相关信息。

#### 6.7.4.18. `mpo_check_socket_send`

`int fsfuncmpo_check_socket_send(` | cred, |
| so, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *so`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`so` | 套接字 |
`socketlabel` | `so`的策略标记 |

决定该主体是否有权通过套接字`so`发送信息。

#### 6.7.4.19. `mpo_check_cred_visible`

`int fsfuncmpo_check_cred_visible(` | u1, |
| u2`)`; |

`struct ucred *u1`;
`struct ucred *u2`;

参数 | 说明 | 锁定
--- | --- | ---
`u1` | 主体信任状 |
`u2` | 对象信任状 |

确定该主体信任状`u1`是否有权 “see” 具有信任状`u2` 的其他主体。 成功，返回0；否则，返回错误编码`errno`。建议采用的错误编码有： EACCES，用于标记不符的情况；EPERM，用于特权不足的情况；ESRCH， 用来提供不可见性。该函数可在许多环境下使用，包括命令`ps`所使用的进程间的状态 sysctl，以及通过procfs 的状态查询操作。

#### 6.7.4.20. `mpo_check_socket_visible`

`int fsfuncmpo_check_socket_visible(` | cred, |
| socket, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *socket`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`socket` | 客体；套接字 |
`socketlabel` | `socket`的策略标记 |

#### 6.7.4.21. `mpo_check_ifnet_relabel`

`int fsfuncmpo_check_ifnet_relabel(` | cred, |
| ifnet, |
| ifnetlabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`ifnet` | 客体；网络接口 |
`ifnetlabel` | `ifnet`现有的策略标记 |
`newlabel` | 将被应用到`ifnet`上的新的策略标记 |

决定该主体信任状是否有权使用传入的标记更新参数对给定的网络接口的标记进行重新设置。

#### 6.7.4.22. `mpo_check_socket_relabel`

`int fsfuncmpo_check_socket_relabel(` | cred, |
| socket, |
| socketlabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct socket *socket`;
`struct label *socketlabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`socket` | 客体；套接字 |
`socketlabel` | `socket`现有的策略标记 |
`newlabel` | 将被应用到`socketlabel`上的更新标记 |

决定该主体信任状是否有权采用传入的标记对套接字参数的标记进行重新设置。

#### 6.7.4.23. `mpo_check_cred_relabel`

`int fsfuncmpo_check_cred_relabel(` | cred, |
| newlabel`)`; |

`struct ucred *cred`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`newlabel` | 将被应用到`cred`上的更新标记 |

决定该主体信任状是否有权将自己的标记重新设置为给定的更新标记。

#### 6.7.4.24. `mpo_check_vnode_relabel`

`int fsfuncmpo_check_vnode_relabel(` | cred, |
| vp, |
| vnodelabel, |
| newlabel`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *vnodelabel`;
`struct label *newlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`vp` | 客体；vnode | 已被锁定
`vnodelabel` | `vp`现有的策略标记 |
`newlabel` | 将被应用到`vp`上的策略标记 |

决定该主体信任状是否有权将参数 vnode 的标记重新设置为指定标记。

#### 6.7.4.25. `mpo_check_mount_stat`

`int fsfuncmpo_check_mount_stat(` | cred, |
| mp, |
| mountlabel`)`; |

`struct ucred *cred`;
`struct mount *mp`;
`struct label *mountlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`mp` | 客体；文件系统挂载 |
`mountlabel` | `mp`的策略标记 |

确定相关主体信任状是否有权查看在给定文件系统上执行 statfs 的结果。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。 该函数可能在下列情况下被调用： 在 statfs(2) 和其他相关调用期间，或者当需要从文件系统列表中选择排除哪个文件系统时，比如， 调用 getfsstat(2)时。

#### 6.7.4.26. `mpo_check_proc_debug`

`int fsfuncmpo_check_proc_debug(` | cred, |
| proc`)`; |

`struct ucred *cred`;
`struct proc *proc`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`proc` | 客体；进程 |

确定相关主体信任状是否有权 debug 给定进程。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够； ESRCH，用于隐瞒目标的存在。 ptrace(2) 和 ktrace(2) API，以及某些 procfs 操作将调用该函数。

#### 6.7.4.27. `mpo_check_vnode_access`

`int fsfuncmpo_check_vnode_access(` | cred, |
| vp, |
| label, |
| flags`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int flags`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`flags` | access(2) 标志 |

根据相关主体信任状决定其对给定 vnode 以给定访问标志执行的 access(2) 和其他相关调用的返回值。一般，应采用与`mpo_check_vnode_open` 相同的语义来实现该函数。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.28. `mpo_check_vnode_chdir`

`int fsfuncmpo_check_vnode_chdir(` | cred, |
| dvp, |
| dlabel`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 客体；chdir(2) 的目的 vnode |
`dlabel` | `dvp`的策略标记 |

确定相关主体信任状是否有权将进程工作目录切换到给定 vnode。成功，则返回 0； 否则，返回一个 `errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.29. `mpo_check_vnode_chroot`

`int fsfuncmpo_check_vnode_chroot(` | cred, |
| dvp, |
| dlabel`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 目录 vnode |
`dlabel` | 与`dvp`相关联的策略标记 |

确定相关主体是否有权 chroot(2) 到由 (`dvp`)给定的目录。

#### 6.7.4.30. `mpo_check_vnode_create`

`int fsfuncmpo_check_vnode_create(` | cred, |
| dvp, |
| dlabel, |
| cnp, |
| vap`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct componentname *cnp`;
`struct vattr *vap`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 客体；vnode |
`dlabel` | `dvp`的策略标记 |
`cnp` | `dvp`中的成员名 |
`vap` | `vap`的 vnode 属性 |

确定相关主体信任状是否有权在给定父目录，以给定的名字和属性， 常见一个 vnode。成功，则返回 0；否则， 返回一个`errno`值。 建议使用的错误编码：EACCES 来表示用于标记不匹配， 而用 EPERM，用于权限不足。 以O_CREAT为参数调用 open(2)，或对 mknod(2)，mkfifo(2) 等的调用将导致该函数被调用。

#### 6.7.4.31. `mpo_check_vnode_delete`

`int fsfuncmpo_check_vnode_delete(` | cred, |
| dvp, |
| dlabel, |
| vp, |
| label, |
| cnp`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct vnode *vp`;
`void *label`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 父目录 vnode |
`dlabel` | `dvp`的策略标记 |
`vp` | 客体；将被删除的 vnode |
`label` | `vp`的策略标记 |
`cnp` | `vp`中的成员名 |

确定相关主体信任状是否有权从给定的父目录中，删除给定名字的 vnode。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。 使用 unlink(2) 和 rmdir(2)，将导致该函数被调用。 提供该入口函数的策略还必须实现一个 `mpo_check_rename_to`， 用来授权由于重命名操作导致的目标文件的删除。

#### 6.7.4.32. `mpo_check_vnode_deleteacl`

`int fsfuncmpo_check_vnode_deleteacl(` | cred, |
| vp, |
| label, |
| type`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`acl_type_t type`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`vp` | 客体；vnode | 被锁定
`label` | `vp`的策略标记 |
`type` | ACL 类型 |

确定相关主体信任状是否有权删除给定 vnode 的给定类型的 ACL。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.33. `mpo_check_vnode_exec`

`int fsfuncmpo_check_vnode_exec(` | cred, |
| vp, |
| label`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；将被执行的 vnode |
`label` | `vp`的策略标记 |

确定相关主体信任状是否有权执行给定 vnode。 对于执行特权的决策与任何瞬时事件的决策是严格分开的。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.34. `mpo_check_vnode_getacl`

`int fsfuncmpo_check_vnode_getacl(` | cred, |
| vp, |
| label, |
| type`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`acl_type_t type`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`type` | ACL 类型 |

确定相关主体信任状是否有权查询给定 vnode 上的给定类型的 ACL。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.35. `mpo_check_vnode_getextattr`

`int fsfuncmpo_check_vnode_getextattr(` | cred, |
| vp, |
| label, |
| attrnamespace, |
| name, |
| uio`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int attrnamespace`;
`const char *name`;
`struct uio *uio`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`attrnamespace` | 扩展属性名字空间 |
`name` | 扩展属性名 |
`uio` | I/O 结构指针；参见 uio(9) |

确定相关主体信任状是否有权查询给定 vnode 上给定名字空间和名字的扩展属性。 使用扩展属性实现标记存储的策略模块可能会需要对这些扩展属性的操作进行特殊处理。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.36. `mpo_check_vnode_link`

`int fsfuncmpo_check_vnode_link(` | cred, |
| dvp, |
| dlabel, |
| vp, |
| label, |
| cnp`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct vnode *vp`;
`struct label *label`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 目录 vnode |
`dlabel` | 与`dvp`相关联的策略标记 |
`vp` | 链接目的 vnode |
`label` | 与`vp`相关联的策略标记 |
`cnp` | 将被创建的链接对应的成员名 |

确定相关主体是否有权为参数`vp`给定的 vnode 创建一个由参数`cnp`给定名字的链接。

#### 6.7.4.37. `mpo_check_vnode_mmap`

`int fsfuncmpo_check_vnode_mmap(` | cred, |
| vp, |
| label, |
| prot`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int prot`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 将被映射的 vnode |
`label` | 与`vp`相关联的策略标记 |
`prot` | mmap 保护 (参见 mmap(2)) |

确定相关主体是否有权将给定 vnode `vp` 以 `prot`指定的保护方式进行映射.

#### 6.7.4.38. `mpo_check_vnode_mmap_downgrade`

`void fsfuncmpo_check_vnode_mmap_downgrade(` | cred, |
| vp, |
| label, |
| prot`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int *prot`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | See 第 6.7.4.37 节 “`mpo_check_vnode_mmap`”. |
`vp` |
`label` |
`prot` | 将被降级的 mmap protections |

根据主体和客体标记，降低 mmap protections。

#### 6.7.4.39. `mpo_check_vnode_mprotect`

`int fsfuncmpo_check_vnode_mprotect(` | cred, |
| vp, |
| label, |
| prot`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int prot`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 映射的 vnode |
`prot` | 存储保护 |

确定相关主体是否有权将给定 vnode`vp` 映射内存空间的存储保护参数设置为指定值。

#### 6.7.4.40. `mpo_check_vnode_poll`

`int fsfuncmpo_check_vnode_poll(` | active_cred, |
| file_cred, |
| vp, |
| label`)`; |

`struct ucred *active_cred`;
`struct ucred *file_cred`;
`struct vnode *vp`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`active_cred` | 主体信任状 |
`file_cred` | 与struct file相关联的信任状 |
`vp` | 将被执行 poll 操作的 vnode |
`label` | 与`vp`相关联的策略标记 |

确定相关主体是否有权对给定 vnode `vp`执行 poll 操作。

#### 6.7.4.41. `mpo_check_vnode_rename_from`

`int fsfuncmpo_vnode_rename_from(` | cred, |
| dvp, |
| dlabel, |
| vp, |
| label, |
| cnp`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct vnode *vp`;
`struct label *label`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 目录 vnode |
`dlabel` | 与`dvp`相关联的策略标记 |
`vp` | 将被重命名的 vnode |
`label` | 与`vp`相关联的策略标记 |
`cnp` | `vp`中的成员名 |

确定相关主体是否有权重命名给定vnode，`vp`。

#### 6.7.4.42. `mpo_check_vnode_rename_to`

`int fsfuncmpo_check_vnode_rename_to(` | cred, |
| dvp, |
| dlabel, |
| vp, |
| label, |
| samedir, |
| cnp`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct vnode *vp`;
`struct label *label`;
`int samedir`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 目录 vnode |
`dlabel` | 与`dvp`相关联的策略标记 |
`vp` | 被覆盖的 vnode |
`label` | 与`vp`相关联的策略标记 |
`samedir` | 布尔型变量；如果源和目的目录是相同的，则被置为`1` |
`cnp` | 目标component名 |

确定相关主体是否有权重命名给定 vnode `vp`，至指定目录 `dvp`，或更名为`cnp`。如果无需覆盖已有文件， 则`vp` 和 `label` 的值将为 NULL.

#### 6.7.4.43. `mpo_check_socket_listen`

`int fsfuncmpo_check_socket_listen(` | cred, |
| socket, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *socket`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`socket` | 客体；套接字 |
`socketlabel` | `socket`的策略标记 |

确定相关主体是否有权监听给定套接字。 成功，则返回0；否则，返回错误编码值`errno`。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.44. `mpo_check_vnode_lookup`

`int fsfuncmpo_check_vnode_lookup(` | , |
| , |
| , |
| cnp`)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;
`struct componentname *cnp`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 客体；vnode |
`dlabel` | `dvp`的策略标记 |
`cnp` | 被检查的成员名 |

确定相关主体信任状是否有权在给定的目录 vnode 中为查找给定名字执行lookup操作。 成功，则返回 0；否则，返回一个 `errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.45. `mpo_check_vnode_open`

`int fsfuncmpo_check_vnode_open(` | cred, |
| vp, |
| label, |
| acc_mode`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int acc_mode`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`acc_mode` | open(2) 访问模式 |

确定相关主体信任状是否有权在给定 vnode 上以给定的访问模式执行 open 操作。 如果成功，则返回 0；否则，返回一个错误编码。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.46. `mpo_check_vnode_readdir`

`int fsfuncmpo_check_vnode_readdir(` | , |
| , |
| `)`; |

`struct ucred *cred`;
`struct vnode *dvp`;
`struct label *dlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`dvp` | 客体；目录 vnode |
`dlabel` | `dvp`的策略标记 |

确定相关主体信任状是否有权在给定的目录 vnode 上执行 `readdir` 操作。 成功，则返回 0；否则，返回一个错误编码 `errno`。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够。

#### 6.7.4.47. `mpo_check_vnode_readlink`

`int fsfuncmpo_check_vnode_readlink(` | cred, |
| vp, |
| label`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |

确定相关主体信任状是否有权在给定符号链接 vnode 上执行 `readlink` 操作。成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够。 该函数可能在若干环境下被调用，包括由用户进程显式执行的 `readlink` 调用， 或者是在进程执行名字查询时隐式执行的 `readlink` 。

#### 6.7.4.48. `mpo_check_vnode_revoke`

`int fsfuncmpo_check_vnode_revoke(` | cred, |
| vp, |
| label`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |

确定相关主体信任状是否有权撤销对给定 vnode 的访问。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够。

#### 6.7.4.49. `mpo_check_vnode_setacl`

`int fsfuncmpo_check_vnode_setacl(` | cred, |
| vp, |
| label, |
| type, |
| acl`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`acl_type_t type`;
`struct acl *acl`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`type` | ACL 类型 |
`acl` | ACL |

确定相关主体信任状是否有权设置给定 vnode 的给定类型的 ACL。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够。

#### 6.7.4.50. `mpo_check_vnode_setextattr`

`int fsfuncmpo_check_vnode_setextattr(` | cred, |
| vp, |
| label, |
| attrnamespace, |
| name, |
| uio`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`int attrnamespace`;
`const char *name`;
`struct uio *uio`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`attrnamespace` | 扩展属性名字空间 |
`name` | 扩展属性名 |
`uio` | I/O 结构指针；参见 uio(9) |

确定相关主体信任状是否有权设置给定 vnode 上给定名字空间中给定名字的扩展属性的值。 使用扩展属性备份安全标记的策略模块可能需要对其使用的属性实施额外的保护。另外， 由于在检查和实际操作时间可能存在的竞争， 策略模块应该避免根据来自`uio`中的数据做出决策。 如果正在执行一个删除操作，则参数 `uio` 的值也可能为 `NULL`。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配；EPERM，用于权限不够。

#### 6.7.4.51. `mpo_check_vnode_setflags`

`int fsfuncmpo_check_vnode_setflags(` | cred, |
| vp, |
| label, |
| flags`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`u_long flags`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`flags` | 文件标志；参见 chflags(2) |

确定相关主体信任状是否有权为给定的 vnode 设置给定的标志。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.52. `mpo_check_vnode_setmode`

`int fsfuncmpo_check_vnode_setmode(` | cred, |
| vp, |
| label, |
| mode`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`mode_t mode`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`mode` | 文件模式；参见 chmod(2) |

确定相关主体信任状是否有权将给定 vnode 的模式设置为给定值。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.53. `mpo_check_vnode_setowner`

`int fsfuncmpo_check_vnode_setowner(` | cred, |
| vp, |
| label, |
| uid, |
| gid`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`uid_t uid`;
`gid_t gid`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |
`uid` | 用户ID |
`gid` | 组ID |

确定相关主体信任状是否有权将给定 vnode 的文件 uid 和文件 gid 设置为给定值。如果无需更新， 相关参数值可能被设置为(`-1`)。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.54. `mpo_check_vnode_setutimes`

`int fsfuncmpo_check_vnode_setutimes(` | , |
| , |
| , |
| , |
| `)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;
`struct timespec atime`;
`struct timespec mtime`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vp |
`label` | `vp`的策略标记 |
`atime` | 访问时间；参见 utimes(2) |
`mtime` | 修改时间；参见 utimes(2) |

确定相关主体信任状是否有权将给定 vnode 的访问时间标签设置为给定值。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.55. `mpo_check_proc_sched`

`int fsfuncmpo_check_proc_sched(` | ucred, |
| proc`)`; |

`struct ucred *ucred`;
`struct proc *proc`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`proc` | 客体；进程 |

确定相关主体信任状是否有权改变给定进程的调度参数。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够； ESRCH，用于提供不可见性质。

See setpriority(2) for more information.

#### 6.7.4.56. `mpo_check_proc_signal`

`int fsfuncmpo_check_proc_signal(` | cred, |
| proc, |
| signal`)`; |

`struct ucred *cred`;
`struct proc *proc`;
`int signal`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`proc` | 客体；进程 |
`signal` | 信号；参见 kill(2) |

确定相关主体信任状是否有权向给定进程发送给定信号。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES， 用于标记不匹配；EPERM，用于权限不够； ESRCH，用于提供不可见性质。

#### 6.7.4.57. `mpo_check_vnode_stat`

`int fsfuncmpo_check_vnode_stat(` | cred, |
| vp, |
| label`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *label`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | 客体；vnode |
`label` | `vp`的策略标记 |

确定相关主体信任状是否有权在给定 vnode 上执行 `stat` 操作。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

See stat(2) for more information.

#### 6.7.4.58. `mpo_check_ifnet_transmit`

`int fsfuncmpo_check_ifnet_transmit(` | cred, |
| ifnet, |
| ifnetlabel, |
| mbuf, |
| mbuflabel`)`; |

`struct ucred *cred`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct mbuf *mbuf`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`ifnet` | 网络接口 |
`ifnetlabel` | `ifnet`的策略标记 |
`mbuf` | 客体；将被发送的 mbuf |
`mbuflabel` | `mbuf`的策略标记 |

确定相关网络接口是否有权传送给定的 mbuf。成功，则返回 0； 否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.59. `mpo_check_socket_deliver`

`int fsfuncmpo_check_socket_deliver(` | cred, |
| ifnet, |
| ifnetlabel, |
| mbuf, |
| mbuflabel`)`; |

`struct ucred *cred`;
`struct ifnet *ifnet`;
`struct label *ifnetlabel`;
`struct mbuf *mbuf`;
`struct label *mbuflabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`ifnet` | 网络接口 |
`ifnetlabel` | `ifnet`的策略标记 |
`mbuf` | 客体；将被传送的 mbuf |
`mbuflabel` | `mbuf`的策略标记 |

确定相关套接字是否有权从给定的 mbuf 中接收数据报。 成功，则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够。

#### 6.7.4.60. `mpo_check_socket_visible`

`int fsfuncmpo_check_socket_visible(` | cred, |
| so, |
| socketlabel`)`; |

`struct ucred *cred`;
`struct socket *so`;
`struct label *socketlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 | 不可改变
`so` | 客体；套接字 |
`socketlabel` | `so`的策略标记 |

确定相关主体信任状cred 是否有权使用系统监控函数，比如， 由netstat(8) 和 sockstat(1)使用的程序来观察 给定的套接字(`socket`)。成功， 则返回 0；否则，返回一个`errno`值。 建议使用的错误编码：EACCES，用于标记不匹配； EPERM，用于权限不够； ESRCH，用于提供不可见性质。

#### 6.7.4.61. `mpo_check_system_acct`

`int fsfuncmpo_check_system_acct(` | ucred, |
| vp, |
| vlabel`)`; |

`struct ucred *ucred`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`ucred` | 主体信任状 |
`vp` | 审计文件；acct(5) |
`vlabel` | 与`vp`相关联的标记 |

根据主体标记和审计日志文件的标记，确定该主体是否有权启动审计。

#### 6.7.4.62. `mpo_check_system_nfsd`

`int fsfuncmpo_check_system_nfsd(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |

确定相关主体是否有权调用 nfssvc(2)。

#### 6.7.4.63. `mpo_check_system_reboot`

`int fsfuncmpo_check_system_reboot(` | cred, |
| howto`)`; |

`struct ucred *cred`;
`int howto`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`howto` | 来自 reboot(2)的`howto` 参数 |

确定相关主体是否有权以指定方式重启系统。

#### 6.7.4.64. `mpo_check_system_settime`

`int fsfuncmpo_check_system_settime(` | cred`)`; |

`struct ucred *cred`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |

确定相关用户是否有权设置系统时钟。

#### 6.7.4.65. `mpo_check_system_swapon`

`int fsfuncmpo_check_system_swapon(` | cred, |
| vp, |
| vlabel`)`; |

`struct ucred *cred`;
`struct vnode *vp`;
`struct label *vlabel`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`vp` | swap设备 |
`vlabel` | 与`vp`相关联的标记 |

确定相关主体是否有权增加一个作为swap设备的 `vp` 。

#### 6.7.4.66. `mpo_check_system_sysctl`

`int fsfuncmpo_check_system_sysctl(` | cred, |
| name, |
| namelen, |
| old, |
| oldlenp, |
| inkernel, |
| new, |
| newlen`)`; |

`struct ucred *cred`;
`int *name`;
`u_int *namelen`;
`void *old`;
`size_t *oldlenp`;
`int inkernel`;
`void *new`;
`size_t newlen`;

参数 | 说明 | 锁定
--- | --- | ---
`cred` | 主体信任状 |
`name` | 参见 sysctl(3) |
`namelen` |
`old` |
`oldlenp` |
`inkernel` | 布尔型变量；如果从内核被调用，其值被置为`1` |
`new` | 参见 sysctl(3) |
`newlen` |

确定相关主体是否应该被允许执行指定的 sysctl(3) 事务。

### 6.7.5. 标记管理调用

当用户进程请求对某个对象的标记进行修改时，将引发重新标记事件。对应的更新操作分两步进行： 首先，进行访问控制检查，确认此次更新操作是有效且被允许的；然后，调用另一个独立的入口函数对标记进行修改。 重新标记入口函数通常接收由请求进程提交的对象、对象标记指针和请求新标记，作为输入参数。 对象重新标记操作的失败将由先期的标记检查报告，所以，不允许在接下来的标记修改过程中报告失败，故而不提倡在此过程中新分配内存。

上一页 | 上一级 | 下一页
6.6. MAC策略模块体系结构 | 起始页 | 6.8. 应用层体系结构

本文档和其它文档可从这里下载： ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题，请先阅读 文档，如不能解决再联系 <questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.