<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>瑙哥空间</title><link>http://152.136.151.227/</link><description>我的技术之旅-分享已知的一切</description><item><title>利用Linux NS和cGroups机制简单实现容器进程划分</title><link>http://152.136.151.227/?id=20</link><description>&lt;h1 id=&quot;h1--ns-cgroup-&quot;&gt;&lt;a name=&quot;利用NS和cGroup区分容器进程和非容器进程&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;利用NS和cGroup区分容器进程和非容器进程&lt;/h1&gt;&lt;h2 id=&quot;h2-u6838u5FC3u601Du8DEF&quot;&gt;&lt;a name=&quot;核心思路&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;核心思路&lt;/h2&gt;&lt;p&gt;在 Linux 系统中，容器技术的核心是 命名空间 (Namespace) 和 控制组 (Cgroups)。我们可以利用这些内核特性来识别一个进程是否运行在容器内。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PID 命名空间 (PID Namespace): 每个容器都有自己独立的进程ID空间。容器内的1号进程对应于宿主机上的一个普通进程。因此，一个进程的 PID 命名空间如果与宿主机 init 进程（PID为1）的 PID 命名空间不同，那么它极有可能是一个容器进程。

Cgroups: 容器运行时（如 Docker、containerd）会为每个容器创建特定的 Cgroup 路径，用于资源限制。通过检查进程的 /proc/[pid]/cgroup 文件，我们可以看到它所属的 Cgroup 路径。容器进程的 Cgroup 路径通常包含 docker、kubepods 或 container 等特征字符串。&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;本项目将主要采用第一种方法（PID 命名空间），因为它是一种更通用和根本性的区分方式。&lt;/p&gt;
&lt;p&gt;我们将通过 eBPF 实现以下逻辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;内核态 (eBPF Program): 附加一个 eBPF 程序到内核的进程创建相关的跟踪点（例如 sched_process_exec）。当系统中有新进程执行时，该 eBPF 程序会被触发。程序会获取新进程的 task_struct 结构体，并从中读取其 PID 命名空间的 inode 号。

用户态 (User-space Application):

    启动时，首先获取宿主机 init 进程（PID 1）的 PID 命名空间 inode 号，并将其作为“基准”写入一个 eBPF Map 中，供内核态的 eBPF 程序查询。

    加载 eBPF 程序并将其附加到指定的内核跟踪点。

    通过 eBPF 的 Perf Event Array 机制，接收内核态 eBPF 程序发送的事件。

    内核态程序会将每个新进程的 PID、COMM（进程名）及其 PID 命名空间 inode 号与宿主机基准 inode 号的对比结果发送给用户态。

    用户态程序接收到数据后，进行格式化输出，明确标识出哪些是容器进程，哪些是宿主机进程。&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;系统架构&lt;/p&gt;
&lt;p&gt;+————————————————-+&lt;br&gt;|               User Space (C/Go/Rust)            |&lt;br&gt;|  +——————————————-+  |&lt;br&gt;|  |             Loader Application            |  |&lt;br&gt;|  |——————————————-|  |&lt;br&gt;|  | 1. Get host init ns inode                 |  |&lt;br&gt;|  | 2. Load eBPF object file                  |  |&lt;br&gt;|  | 3. Write host ns inode to BPF_MAP       &amp;lt;—-&lt;br&gt;|  | 4. Attach eBPF program to tracepoint      |  | | BPF_MAP_TYPE_HASH&lt;br&gt;|  | 5. Read events from Perf Buffer         &amp;lt;—- (for host ns)&lt;br&gt;|  +——————————————-+  | |&lt;br&gt;+———————-^————————–+&lt;br&gt;                       | Perf Buffer&lt;br&gt;                       | (BPF_MAP_TYPE_PERF_EVENT_ARRAY)&lt;br&gt;+———————-|————————–+&lt;br&gt;|                      v                          |&lt;br&gt;|                Kernel Space                     |&lt;br&gt;|  +——————————————-+  |&lt;br&gt;|  |              eBPF Program               |  |&lt;br&gt;|  |——————————————-|  |&lt;br&gt;|  | TRACEPOINT(sched_process_exec)            |  |&lt;br&gt;|  | {                                         |  |&lt;br&gt;|  |   task = bpf_get_current_task();          |  |&lt;br&gt;|  |   process_ns_inode = task-&amp;gt;nsproxy-&amp;gt;…;  |  |&lt;br&gt;|  |   host_ns_inode = bpf_map_lookup(…);    |  | —-&amp;gt; Read host_ns_inode&lt;br&gt;|  |                                         |  |&lt;br&gt;|  |   is_container = (process_ns_inode !=    |  |&lt;br&gt;|  |                   host_ns_inode);         |  |&lt;br&gt;|  |                                         |  |&lt;br&gt;|  |   bpf_perf_event_output(…);             |  | —-&amp;gt; Send event data&lt;br&gt;|  | }                                         |  |&lt;br&gt;|  +——————————————-+  |&lt;br&gt;+————————————————-+&lt;/p&gt;
&lt;p&gt;完整源码&lt;/p&gt;
&lt;p&gt;本项目包含三个文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;process_classifier.bpf.c: 内核态的 eBPF C 程序。

process_classifier.c: 用户态的加载器和事件处理 C 程序。

Makefile: 用于编译和构建项目的脚本。&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;内核态 eBPF 程序 (process_classifier.bpf.c)&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;此文件定义了 eBPF 程序的核心逻辑。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
#include &amp;lt;linux/bpf.h&amp;gt;
#include &amp;lt;bpf/bpf_helpers.h&amp;gt;
#include &amp;lt;bpf/bpf_core_read.h&amp;gt;
#include &amp;quot;vmlinux.h&amp;quot;

// 定义发送给用户态的事件结构体
struct event {
    u32 pid;
    u32 ppid;
    char comm[TASK_COMM_LEN];
    bool is_container;
};

// Perf event map to send data to user space
struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    __uint(key_size, sizeof(u32));
    __uint(value_size, sizeof(u32));
} events SEC(&amp;quot;.maps&amp;quot;);

// Map to store the host&amp;#39;s init PID namespace inode number
// The user-space program will write to this map.
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1);
    __type(key, u32);
    __type(value, u64);
} host_pid_ns_map SEC(&amp;quot;.maps&amp;quot;);

// Attach to the sched_process_exec tracepoint.
// This is not a raw tracepoint, so the context is task_struct.
SEC(&amp;quot;tp/sched/sched_process_exec&amp;quot;)
int handle_exec(struct trace_event_raw_sched_process_exec *ctx)
{
    struct task_struct *task;
    struct event event = {};
    u64 pid_tgid;
    u32 key = 0;
    u64 *host_pid_ns_inode;
    u64 proc_pid_ns_inode;

    // Get PID and TGID
    pid_tgid = bpf_get_current_pid_tgid();
    event.pid = pid_tgid &amp;gt;&amp;gt; 32;

    // Get current task_struct
    task = (struct task_struct *)bpf_get_current_task();

    // Get parent PID
    event.ppid = BPF_CORE_READ(task, real_parent, tgid);

    // Get command name
    bpf_get_current_comm(&amp;amp;event.comm, sizeof(event.comm));

    // Get the PID namespace inode number for the current process
    // task-&amp;gt;nsproxy-&amp;gt;pid_ns_for_children-&amp;gt;ns.inum
    proc_pid_ns_inode = BPF_CORE_READ(task, nsproxy, pid_ns_for_children, ns.inum);

    // Look up the host PID namespace inode from the map
    host_pid_ns_inode = bpf_map_lookup_elem(&amp;amp;host_pid_ns_map, &amp;amp;key);

    if (host_pid_ns_inode) {
        // If the process&amp;#39;s PID namespace inode is different from the host&amp;#39;s,
        // it&amp;#39;s a container process.
        if (proc_pid_ns_inode != *host_pid_ns_inode) {
            event.is_container = true;
        } else {
            event.is_container = false;
        }
    } else {
        // If map lookup fails, we can&amp;#39;t determine, assume not a container.
        event.is_container = false;
    }

    // Send the event to user space via the perf buffer.
    bpf_perf_event_output(ctx, &amp;amp;events, BPF_F_CURRENT_CPU, &amp;amp;event, sizeof(event));

    return 0;
}

char LICENSE[] SEC(&amp;quot;license&amp;quot;) = &amp;quot;Dual BSD/GPL&amp;quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;用户态加载器 (process_classifier.c)&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;此文件负责加载 eBPF 程序、与内核交互并显示结果。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;sys/resource.h&amp;gt;
#include &amp;lt;bpf/libbpf.h&amp;gt;
#include &amp;lt;time.h&amp;gt;
#include &amp;lt;errno.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;quot;process_classifier.skel.h&amp;quot;

// 定义与内核态一致的事件结构体
struct event {
    __u32 pid;
    __u32 ppid;
    char comm[16];
    bool is_container;
};

// 获取指定PID的PID命名空间inode号
static unsigned long long get_pid_ns_inode(pid_t pid) {
    char path[128];
    struct stat s;

    snprintf(path, sizeof(path), &amp;quot;/proc/%d/ns/pid&amp;quot;, pid);
    if (stat(path, &amp;amp;s) != 0) {
        perror(&amp;quot;Failed to stat pid namespace&amp;quot;);
        return 0;
    }
    return s.st_ino;
}

// Perf buffer 事件处理回调函数
static int handle_event(void *ctx, void *data, size_t data_sz) {
    const struct event *e = data;
    time_t t;
    struct tm *tm;
    char ts[32];

    time(&amp;amp;t);
    tm = localtime(&amp;amp;t);
    strftime(ts, sizeof(ts), &amp;quot;%H:%M:%S&amp;quot;, tm);

    printf(&amp;quot;%-8s %-7d %-7d %-16s %-10s\n&amp;quot;,
           ts, e-&amp;gt;pid, e-&amp;gt;ppid, e-&amp;gt;comm,
           e-&amp;gt;is_container ? &amp;quot;Container&amp;quot; : &amp;quot;Host&amp;quot;);

    return 0;
}

int main(int argc, char **argv) {
    struct process_classifier_bpf *skel;
    struct perf_buffer *pb = NULL;
    int err;
    unsigned long long host_init_pid_ns;
    int map_fd;
    int key = 0;

    // 提升资源限制
    struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
    if (setrlimit(RLIMIT_MEMLOCK, &amp;amp;r)) {
        perror(&amp;quot;setrlimit(RLIMIT_MEMLOCK)&amp;quot;);
        return 1;
    }

    // 1. 打开、加载并验证 eBPF 程序
    skel = process_classifier_bpf__open_and_load();
    if (!skel) {
        fprintf(stderr, &amp;quot;Failed to open and load BPF skeleton\n&amp;quot;);
        return 1;
    }

    // 2. 获取宿主机 init 进程 (PID=1) 的 PID Namespace Inode
    host_init_pid_ns = get_pid_ns_inode(1);
    if (host_init_pid_ns == 0) {
        fprintf(stderr, &amp;quot;Failed to get host init pid namespace inode\n&amp;quot;);
        goto cleanup;
    }
    printf(&amp;quot;Host init PID namespace inode: %llu\n&amp;quot;, host_init_pid_ns);

    // 3. 将宿主机 PID Namespace Inode 写入 eBPF map
    map_fd = bpf_map__fd(skel-&amp;gt;maps.host_pid_ns_map);
    err = bpf_map_update_elem(map_fd, &amp;amp;key, &amp;amp;host_init_pid_ns, BPF_ANY);
    if (err) {
        fprintf(stderr, &amp;quot;Failed to update host_pid_ns_map: %s\n&amp;quot;, strerror(errno));
        goto cleanup;
    }

    // 4. 附加 eBPF 程序到跟踪点
    err = process_classifier_bpf__attach(skel);
    if (err) {
        fprintf(stderr, &amp;quot;Failed to attach BPF skeleton: %d\n&amp;quot;, err);
        goto cleanup;
    }

    printf(&amp;quot;Successfully started! Please run processes on host or in containers to see events.\n&amp;quot;);
    printf(&amp;quot;%-8s %-7s %-7s %-16s %-10s\n&amp;quot;, &amp;quot;TIME&amp;quot;, &amp;quot;PID&amp;quot;, &amp;quot;PPID&amp;quot;, &amp;quot;COMM&amp;quot;, &amp;quot;TYPE&amp;quot;);

    // 5. 设置 Perf Buffer 来接收事件
    pb = perf_buffer__new(bpf_map__fd(skel-&amp;gt;maps.events), 8, handle_event, NULL, NULL, NULL);
    if (!pb) {
        err = -errno;
        fprintf(stderr, &amp;quot;Failed to create perf buffer: %d\n&amp;quot;, err);
        goto cleanup;
    }

    // 6. 轮询 Perf Buffer
    while (true) {
        err = perf_buffer__poll(pb, 100 /* timeout, ms */);
        if (err &amp;lt; 0 &amp;amp;&amp;amp; err != -EINTR) {
            fprintf(stderr, &amp;quot;Error polling perf buffer: %s\n&amp;quot;, strerror(-err));
            break;
        }
    }

cleanup:
    perf_buffer__free(pb);
    process_classifier_bpf__destroy(skel);
    return -err;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Makefile&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;这个 Makefile 会处理所有编译步骤，包括使用 bpftool 生成 skeleton 文件。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Makefile&quot;&gt;
# Dirs
SRC_DIR = .
OUT_DIR = .

# Files
BPF_SRC = $(SRC_DIR)/process_classifier.bpf.c
BPF_OBJ = $(OUT_DIR)/process_classifier.bpf.o
BPF_SKEL = $(OUT_DIR)/process_classifier.skel.h
USER_SRC = $(SRC_DIR)/process_classifier.c
USER_BIN = $(OUT_DIR)/process_classifier

# Tools
CC = gcc
CLANG = clang
BPFTOOL = bpftool

# Flags
CFLAGS = -g -Wall
LDFLAGS = -lbpf

.PHONY: all clean

all: $(USER_BIN)

# Generate BPF skeleton header
$(BPF_SKEL): $(BPF_OBJ)
    $(BPFTOOL) gen skeleton $&amp;lt; &amp;gt; $@

# Compile BPF C code to object file
$(BPF_OBJ): $(BPF_SRC)
    $(CLANG) -g -O2 -target bpf -c $&amp;lt; -o $@ -I/usr/include/bpf -I.

# Compile user-space C code
$(USER_BIN): $(USER_SRC) $(BPF_SKEL)
    $(CC) $(CFLAGS) $&amp;lt; -o $@ $(LDFLAGS)

clean:
    rm -f $(BPF_OBJ) $(BPF_SKEL) $(USER_BIN)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-u51C6u5907u548Cu7F16u8BD1u73AFu5883&quot;&gt;&lt;a name=&quot;准备和编译环境&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;准备和编译环境&lt;/h2&gt;&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;安装依赖:&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;安装依赖:&lt;/h3&gt;&lt;p&gt;你需要一个较新的 Linux 内核（推荐 5.8+），以及 clang, llvm, libbpf-dev, 和 bpftool。&lt;br&gt;在 Ubuntu/Debian 上:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;
sudo apt-get update
sudo apt-get install -y clang llvm libelf-dev libbpf-dev bpftool build-essential

获取 vmlinux.h:
eBPF 程序需要内核类型定义。bpftool 可以从你正在运行的内核生成此文件。
Bash

# 确保你的系统支持 BTF (BPF Type Format)
ls /sys/kernel/btf/vmlinux

# 如果上述文件存在，则可以生成 vmlinux.h
bpftool btf dump file /sys/kernel/btf/vmlinux format c &amp;gt; vmlinux.h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 /sys/kernel/btf/vmlinux 不存在，你需要确保你的内核编译时开启了 CONFIG_DEBUG_INFO_BTF=y 选项。&lt;/p&gt;
&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;编译项目:&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;编译项目:&lt;/h3&gt;&lt;p&gt;将以上三个文件 (process_classifier.bpf.c, process_classifier.c, Makefile) 放在同一个目录下，然后运行 make。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;
    make&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;如果一切顺利，你会在当前目录下看到一个名为 process_classifier 的可执行文件。&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;h3-u8FD0u884Cu548Cu9A8Cu8BC1&quot;&gt;&lt;a name=&quot;运行和验证&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;运行和验证&lt;/h3&gt;&lt;p&gt;运行程序:&lt;br&gt;因为 eBPF 程序需要加载到内核，所以需要 root 权限。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;sudo ./process_classifier&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;程序启动后，会打印出宿主机的 init 进程 PID 命名空间 inode，然后开始监听新的进程执行事件。&lt;/p&gt;
&lt;p&gt;验证:&lt;br&gt;打开第一个终端，运行程序:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;sudo ./process_classifier
Host init PID namespace inode: 4026531836
Successfully started! Please run processes on host or in containers to see events.
TIME     PID     PPID    COMM             TYPE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打开第二个终端 (宿主机终端)，执行一些命令:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;ls -l
sleep 5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在第一个终端，你会看到类似这样的输出，TYPE 都是 Host:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;20:42:10 12345   12300   ls               Host
20:42:15 12346   12300   sleep            Host&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;打开第三个终端，启动一个 Docker 容器并执行命令:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Bash&quot;&gt;
# 启动一个交互式 busybox 容器
docker run --rm -it busybox

# 在容器内执行命令
/ # ls
/ # ps aux
/ # sleep 10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在回到第一个终端，你会看到来自容器的进程事件，TYPE 被正确地标识为 Container:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;20:45:30 13010   12990   ls               Container
20:45:35 13011   12990   ps               Container
20:45:40 13012   12990   sleep            Container&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Sun, 12 Oct 2025 18:48:53 +0800</pubDate></item><item><title>Ubuntu2204安装OpenVas【译+一些适配上的见解】</title><link>http://152.136.151.227/?id=19</link><description>&lt;p&gt;译自：&lt;a href=&quot;https://medium.com/@raivishnu1013/install-openvas-gvm-22-4-0-on-ubuntu-22-04-e351fd132a1b&quot;&quot;&gt;https://medium.com/&amp;#64;raivishnu1013/install-openvas-gvm-22-4-0-on-ubuntu-22-04-e351fd132a1b&lt;/a&gt;&lt;br&gt;要在 Ubuntu 22.4.0 中安装 GVM 22.04 而没有任何问题，请在您的计算机中打开一个终端，然后按照本指南进行作。如果您仍然遇到一些问题，请随时发表评论。此外，所有服务都有类似的构建方式，所以我只会解释第一个部分，您可以直接复制和粘贴命令，如果您仍然想知道一些我想提及的内容，评论部分仅供您参考，请让我知道:)&lt;/p&gt;
&lt;p class=&quot;editormd-tex&quot;&gt;推荐一定要科学上网，否则真的很慢&lt;/p&gt;
&lt;p&gt;  创建新用户&lt;/p&gt;
&lt;p&gt;sudo useradd -r -M -U -G sudo -s /usr/sbin/nologin gvm&lt;/p&gt;
&lt;p&gt;将用户添加到 gvmd 组&lt;/p&gt;
&lt;p&gt;sudo usermod -aG gvm $USER&lt;br&gt;su $USER&lt;/p&gt;
&lt;p&gt;  设置 PATH 环境&lt;/p&gt;
&lt;p&gt;export PATH=$PATH:/usr/local/sbin &lt;/p&gt;
&lt;p&gt;设置 Installation Prefix 环境变量&lt;/p&gt;
&lt;p&gt;export INSTALL_PREFIX=/usr/local&lt;/p&gt;
&lt;p&gt;选择源码目录、构建目录和安装目录&lt;/p&gt;
&lt;p&gt;export SOURCE_DIR=$HOME/source&lt;br&gt;mkdir -p $SOURCE_DIR&lt;br&gt;export BUILD_DIR=$HOME/build&lt;br&gt;mkdir -p $BUILD_DIR&lt;br&gt;export INSTALL_DIR=$HOME/install&lt;br&gt;mkdir -p $INSTALL_DIR&lt;/p&gt;
&lt;p&gt;下载并安装以下依赖项：&lt;/p&gt;
&lt;p&gt;sudo apt update&lt;br&gt;sudo apt install –no-install-recommends –assume-yes &lt;br&gt;  build-essential &lt;br&gt;  curl &lt;br&gt;  cmake &lt;br&gt;  pkg-config &lt;br&gt;  python3 &lt;br&gt;  python3-pip &lt;br&gt;  gnupg&lt;/p&gt;
&lt;p&gt;  导入 greenbone 密钥&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://www.greenbone.net/GBCommunitySigningKey.asc&quot;&gt;https://www.greenbone.net/GBCommunitySigningKey.asc&lt;/a&gt; -o /tmp/GBCommunitySigningKey.asc&lt;br&gt;gpg –import /tmp/GBCommunitySigningKey.asc&lt;br&gt;echo “8AE4BE429B60A59B311C2E739823FAA60ED1E580:6:” &amp;gt; /tmp/ownertrust.txt&lt;br&gt;gpg –import-ownertrust &amp;lt; /tmp/ownertrust.txt&lt;/p&gt;
&lt;p&gt;将 GVM 版本设置为如果不设置版本，下载可能会出现问题。（版本可以稍后更改）&lt;/p&gt;
&lt;p&gt; export GVM_VERSION=22.4.0&lt;/p&gt;
&lt;p&gt;  配置 gvm-libs&lt;/p&gt;
&lt;p&gt;export GVM_LIBS_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  libglib2.0-dev &lt;br&gt;  libgpgme-dev &lt;br&gt;  libgnutls28-dev &lt;br&gt;  uuid-dev &lt;br&gt;  libssh-gcrypt-dev &lt;br&gt;  libhiredis-dev &lt;br&gt;  libxml2-dev &lt;br&gt;  libpcap-dev &lt;br&gt;  libnet1-dev &lt;br&gt;  libpaho-mqtt-dev &lt;br&gt;  libldap2-dev &lt;br&gt;  libradcli-dev&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gvm-libs/archive/refs/tags/v$GVM_LIBS_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/gvm-libs/archive/refs/tags/v$GVM_LIBS_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gvm-libs/releases/download/v$GVM_LIBS_VERSION/gvm-libs-$GVM_LIBS_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/gvm-libs/releases/download/v$GVM_LIBS_VERSION/gvm-libs-$GVM_LIBS_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION.tar.gz.asc&lt;br&gt;gpg –verify $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION.tar.gz.asc $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/gvm-libs &amp;amp;&amp;amp; cd $BUILD_DIR/gvm-libs&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/gvm-libs &amp;amp;&amp;amp; cd $BUILD_DIR/gvm-libs&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/gvm-libs-$GVM_LIBS_VERSION &lt;br&gt;  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release &lt;br&gt;  -DSYSCONFDIR=/etc &lt;br&gt;  -DLOCALSTATEDIR=/var&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 gvmd&lt;/p&gt;
&lt;p&gt;export GVMD_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  libglib2.0-dev &lt;br&gt;  libgnutls28-dev &lt;br&gt;  libpq-dev &lt;br&gt;  postgresql-server-dev-14 &lt;br&gt;  libical-dev &lt;br&gt;  xsltproc &lt;br&gt;  rsync &lt;br&gt;  libbsd-dev &lt;br&gt;  libgpgme-dev&lt;/p&gt;
&lt;p&gt;sudo apt install -y –no-install-recommends &lt;br&gt;  texlive-latex-extra &lt;br&gt;  texlive-fonts-recommended &lt;br&gt;  xmlstarlet &lt;br&gt;  zip &lt;br&gt;  rpm &lt;br&gt;  fakeroot &lt;br&gt;  dpkg &lt;br&gt;  nsis &lt;br&gt;  gnupg &lt;br&gt;  gpgsm &lt;br&gt;  wget &lt;br&gt;  sshpass &lt;br&gt;  openssh-client &lt;br&gt;  socat &lt;br&gt;  snmp &lt;br&gt;  python3 &lt;br&gt;  smbclient &lt;br&gt;  python3-lxml &lt;br&gt;  gnutls-bin &lt;br&gt;  xml-twig-tools&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gvmd/archive/refs/tags/v$GVMD_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/gvmd/archive/refs/tags/v$GVMD_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/gvmd-$GVMD_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gvmd/releases/download/v$GVMD_VERSION/gvmd-$GVMD_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/gvmd/releases/download/v$GVMD_VERSION/gvmd-$GVMD_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/gvmd-$GVMD_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/gvmd-$GVMD_VERSION.tar.gz.asc $SOURCE_DIR/gvmd-$GVMD_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/gvmd-$GVMD_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/gvmd &amp;amp;&amp;amp; cd $BUILD_DIR/gvmd&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/gvmd-$GVMD_VERSION &lt;br&gt;  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release &lt;br&gt;  -DLOCALSTATEDIR=/var &lt;br&gt;  -DSYSCONFDIR=/etc &lt;br&gt;  -DGVM_DATA_DIR=/var &lt;br&gt;  -DGVMD_RUN_DIR=/run/gvmd &lt;br&gt;  -DOPENVAS_DEFAULT_SOCKET=/run/ospd/ospd-openvas.sock &lt;br&gt;  -DGVM_FEED_LOCK_PATH=/var/lib/gvm/feed-update.lock &lt;br&gt;  -DSYSTEMD_SERVICE_DIR=/lib/systemd/system &lt;br&gt;  -DLOGROTATE_DIR=/etc/logrotate.d &lt;br&gt;  -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 pg-gvm&lt;/p&gt;
&lt;p&gt;export PG_GVM_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  libglib2.0-dev &lt;br&gt;  postgresql-server-dev-14 &lt;br&gt;  libical-dev&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/pg-gvm/archive/refs/tags/v$PG_GVM_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/pg-gvm/archive/refs/tags/v$PG_GVM_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/pg-gvm/releases/download/v$PG_GVM_VERSION/pg-gvm-$PG_GVM_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/pg-gvm/releases/download/v$PG_GVM_VERSION/pg-gvm-$PG_GVM_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION.tar.gz.asc $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/pg-gvm &amp;amp;&amp;amp; cd $BUILD_DIR/pg-gvm&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/pg-gvm-$PG_GVM_VERSION &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release &lt;br&gt;  -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 GSA&lt;/p&gt;
&lt;p&gt;export GSA_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;export NODE_VERSION=node_14.x&lt;br&gt;export KEYRING=/usr/share/keyrings/nodesource.gpg&lt;br&gt;export DISTRIBUTION=”$(lsb_release -s -c)”&lt;/p&gt;
&lt;p&gt;curl -fsSL &lt;a href=&quot;https://deb.nodesource.com/gpgkey/nodesource.gpg.key&quot;&gt;https://deb.nodesource.com/gpgkey/nodesource.gpg.key&lt;/a&gt; | gpg –dearmor | sudo tee “$KEYRING” &amp;gt;/dev/null&lt;br&gt;gpg –no-default-keyring –keyring “$KEYRING” –list-keys&lt;/p&gt;
&lt;p&gt;echo “deb [signed-by=$KEYRING] &lt;a href=&quot;https://deb.nodesource.com/$NODE_VERSION&quot;&gt;https://deb.nodesource.com/$NODE_VERSION&lt;/a&gt; $DISTRIBUTION main” | sudo tee /etc/apt/sources.list.d/nodesource.list&lt;br&gt;echo “deb-src [signed-by=$KEYRING] &lt;a href=&quot;https://deb.nodesource.com/$NODE_VERSION&quot;&gt;https://deb.nodesource.com/$NODE_VERSION&lt;/a&gt; $DISTRIBUTION main” | sudo tee -a /etc/apt/sources.list.d/nodesource.list&lt;/p&gt;
&lt;p&gt;sudo apt update&lt;br&gt;sudo apt install -y nodejs&lt;/p&gt;
&lt;p&gt;curl -sS &lt;a href=&quot;https://dl.yarnpkg.com/debian/pubkey.gpg&quot;&gt;https://dl.yarnpkg.com/debian/pubkey.gpg&lt;/a&gt; | sudo apt-key add -&lt;br&gt;echo “deb &lt;a href=&quot;https://dl.yarnpkg.com/debian/&quot;&gt;https://dl.yarnpkg.com/debian/&lt;/a&gt; stable main” | sudo tee /etc/apt/sources.list.d/yarn.list&lt;/p&gt;
&lt;p&gt;sudo apt update&lt;br&gt;sudo apt install -y yarn&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gsa/archive/refs/tags/v$GSA_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/gsa/archive/refs/tags/v$GSA_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/gsa-$GSA_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gsa/releases/download/v$GSA_VERSION/gsa-$GSA_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/gsa/releases/download/v$GSA_VERSION/gsa-$GSA_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/gsa-$GSA_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/gsa-$GSA_VERSION.tar.gz.asc $SOURCE_DIR/gsa-$GSA_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/gsa-$GSA_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;cd $SOURCE_DIR/gsa-$GSA_VERSION&lt;/p&gt;
&lt;p&gt;rm -rf build&lt;/p&gt;
&lt;p&gt;yarn #注意这里大概率ui-components报错，可以去package.json里把这行删掉，然后去github上下源码，过程如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 创建依赖目录
mkdir -p ~/source/greenbone/
cd ~/source/greenbone

# 克隆 ui-components 仓库
git clone https://github.com/greenbone/ui-components.git
cd ui-components

# 切换到对应分支（例如 gsa-22.04 兼容的分支）
git checkout master  # 或指定版本分支，如 release-22.04

# 编译并安装到本地
npm install
npm run build
npm link

# 返回gsa目录并创建本地链接
cd ~/source/gsa-22.4.0
npm link @greenbone/ui-components

# 然后再执行
npm i # 这时会跳过ui-components，因为已有本地链接&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yarn build&lt;/p&gt;
&lt;p&gt;sudo mkdir -p $INSTALL_PREFIX/share/gvm/gsad/web/&lt;br&gt;sudo cp -r build/* $INSTALL_PREFIX/share/gvm/gsad/web/&lt;/p&gt;
&lt;p&gt;  配置 GSAD&lt;/p&gt;
&lt;p&gt;export GSAD_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  libmicrohttpd-dev &lt;br&gt;  libxml2-dev &lt;br&gt;  libglib2.0-dev &lt;br&gt;  libgnutls28-dev&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gsad/archive/refs/tags/v$GSAD_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/gsad/archive/refs/tags/v$GSAD_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/gsad-$GSAD_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/gsad/releases/download/v$GSAD_VERSION/gsad-$GSAD_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/gsad/releases/download/v$GSAD_VERSION/gsad-$GSAD_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/gsad-$GSAD_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/gsad-$GSAD_VERSION.tar.gz.asc $SOURCE_DIR/gsad-$GSAD_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/gsad-$GSAD_VERSION.tar.gz  &lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/gsad &amp;amp;&amp;amp; cd $BUILD_DIR/gsad&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/gsad-$GSAD_VERSION &lt;br&gt;  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release &lt;br&gt;  -DSYSCONFDIR=/etc &lt;br&gt;  -DLOCALSTATEDIR=/var &lt;br&gt;  -DGVMD_RUN_DIR=/run/gvmd &lt;br&gt;  -DGSAD_RUN_DIR=/run/gsad &lt;br&gt;  -DLOGROTATE_DIR=/etc/logrotate.d&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 openvas-smb&lt;/p&gt;
&lt;p&gt;export OPENVAS_SMB_VERSION=22.4.0&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  gcc-mingw-w64 &lt;br&gt;  libgnutls28-dev &lt;br&gt;  libglib2.0-dev &lt;br&gt;  libpopt-dev &lt;br&gt;  libunistring-dev &lt;br&gt;  heimdal-dev &lt;br&gt;  perl-base&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/openvas-smb/archive/refs/tags/v$OPENVAS_SMB_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/openvas-smb/archive/refs/tags/v$OPENVAS_SMB_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/openvas-smb/releases/download/v$OPENVAS_SMB_VERSION/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/openvas-smb/releases/download/v$OPENVAS_SMB_VERSION/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz.asc $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/openvas-smb &amp;amp;&amp;amp; cd $BUILD_DIR/openvas-smb&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/openvas-smb-$OPENVAS_SMB_VERSION &lt;br&gt;  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;配置 openvas-scanner&lt;/p&gt;
&lt;p&gt;export OPENVAS_SCANNER_VERSION=$GVM_VERSION&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  bison &lt;br&gt;  libglib2.0-dev &lt;br&gt;  libgnutls28-dev &lt;br&gt;  libgcrypt20-dev &lt;br&gt;  libpcap-dev &lt;br&gt;  libgpgme-dev &lt;br&gt;  libksba-dev &lt;br&gt;  rsync &lt;br&gt;  nmap &lt;br&gt;  libjson-glib-dev &lt;br&gt;  libbsd-dev&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  python3-impacket &lt;br&gt;  libsnmp-dev&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/openvas-scanner/archive/refs/tags/v$OPENVAS_SCANNER_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/openvas-scanner/archive/refs/tags/v$OPENVAS_SCANNER_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/openvas-scanner/releases/download/v$OPENVAS_SCANNER_VERSION/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/openvas-scanner/releases/download/v$OPENVAS_SCANNER_VERSION/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz.asc $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;mkdir -p $BUILD_DIR/openvas-scanner &amp;amp;&amp;amp; cd $BUILD_DIR/openvas-scanner&lt;/p&gt;
&lt;p&gt;cmake $SOURCE_DIR/openvas-scanner-$OPENVAS_SCANNER_VERSION &lt;br&gt;  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX &lt;br&gt;  -DCMAKE_BUILD_TYPE=Release &lt;br&gt;  -DSYSCONFDIR=/etc &lt;br&gt;  -DLOCALSTATEDIR=/var &lt;br&gt;  -DOPENVAS_FEED_LOCK_PATH=/var/lib/openvas/feed-update.lock &lt;br&gt;  -DOPENVAS_RUN_DIR=/run/ospd&lt;/p&gt;
&lt;p&gt;make -j$(nproc)&lt;/p&gt;
&lt;p&gt;make DESTDIR=$INSTALL_DIR install&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 ospd-openvas&lt;/p&gt;
&lt;p&gt;export OSPD_OPENVAS_VERSION=22.4.2&lt;/p&gt;
&lt;p&gt;INSTALL_PREFIX=/usr&lt;br&gt;sudo apt install -y &lt;br&gt;  python3 &lt;br&gt;  python3-pip &lt;br&gt;  python3-setuptools &lt;br&gt;  python3-packaging &lt;br&gt;  python3-wrapt &lt;br&gt;  python3-cffi &lt;br&gt;  python3-psutil &lt;br&gt;  python3-lxml &lt;br&gt;  python3-defusedxml &lt;br&gt;  python3-paramiko &lt;br&gt;  python3-redis &lt;br&gt;  python3-paho-mqtt&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/ospd-openvas/archive/refs/tags/v$OSPD_OPENVAS_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/ospd-openvas/archive/refs/tags/v$OSPD_OPENVAS_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/ospd-openvas/releases/download/v$OSPD_OPENVAS_VERSION/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/ospd-openvas/releases/download/v$OSPD_OPENVAS_VERSION/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz.asc $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;cd $SOURCE_DIR/ospd-openvas-$OSPD_OPENVAS_VERSION&lt;/p&gt;
&lt;p&gt;python3 -m pip install . –prefix=$INSTALL_PREFIX –root=$INSTALL_DIR –no-warn-script-location&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 notus-scanner&lt;/p&gt;
&lt;p&gt;export NOTUS_VERSION=22.4.1&lt;/p&gt;
&lt;p&gt;INSTALL_PREFIX=/usr&lt;br&gt;sudo apt install -y &lt;br&gt;  python3 &lt;br&gt;  python3-pip &lt;br&gt;  python3-setuptools &lt;br&gt;  python3-paho-mqtt &lt;br&gt;  python3-psutil &lt;br&gt;  python3-gnupg&lt;/p&gt;
&lt;p&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/notus-scanner/archive/refs/tags/v$NOTUS_VERSION.tar.gz&quot;&gt;https://github.com/greenbone/notus-scanner/archive/refs/tags/v$NOTUS_VERSION.tar.gz&lt;/a&gt; -o $SOURCE_DIR/notus-scanner-$NOTUS_VERSION.tar.gz&lt;br&gt;curl -f -L &lt;a href=&quot;https://github.com/greenbone/notus-scanner/releases/download/v$NOTUS_VERSION/notus-scanner-$NOTUS_VERSION.tar.gz.asc&quot;&gt;https://github.com/greenbone/notus-scanner/releases/download/v$NOTUS_VERSION/notus-scanner-$NOTUS_VERSION.tar.gz.asc&lt;/a&gt; -o $SOURCE_DIR/notus-scanner-$NOTUS_VERSION.tar.gz.asc&lt;/p&gt;
&lt;p&gt;gpg –verify $SOURCE_DIR/notus-scanner-$NOTUS_VERSION.tar.gz.asc $SOURCE_DIR/notus-scanner-$NOTUS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;tar -C $SOURCE_DIR -xvzf $SOURCE_DIR/notus-scanner-$NOTUS_VERSION.tar.gz&lt;/p&gt;
&lt;p&gt;cd $SOURCE_DIR/notus-scanner-$NOTUS_VERSION&lt;/p&gt;
&lt;p&gt;python3 -m pip install . –prefix=$INSTALL_PREFIX –root=$INSTALL_DIR –no-warn-script-location&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 gvm-tools&lt;/p&gt;
&lt;p&gt;sudo apt install -y &lt;br&gt;  python3 &lt;br&gt;  python3-pip &lt;br&gt;  python3-setuptools &lt;br&gt;  python3-packaging &lt;br&gt;  python3-lxml &lt;br&gt;  python3-defusedxml &lt;br&gt;  python3-paramiko&lt;/p&gt;
&lt;p&gt;python3 -m pip install –user gvm-tools&lt;/p&gt;
&lt;p&gt;python3 -m pip install –prefix=$INSTALL_PREFIX –root=$INSTALL_DIR –no-warn-script-location gvm-tools&lt;/p&gt;
&lt;p&gt;sudo cp -rv $INSTALL_DIR/* /&lt;/p&gt;
&lt;p&gt;  配置 Redis-Server&lt;/p&gt;
&lt;p&gt;sudo apt install -y redis-server&lt;/p&gt;
&lt;p&gt;sudo cp $SOURCE_DIR/openvas-scanner-$GVM_VERSION/config/redis-openvas.conf /etc/redis/&lt;br&gt;sudo chown redis:redis /etc/redis/redis-openvas.conf&lt;br&gt;echo “db_address = /run/redis-openvas/redis.sock” | sudo tee -a /etc/openvas/openvas.conf&lt;/p&gt;
&lt;p&gt;sudo systemctl start &lt;a href=&quot;mailto:redis-&lt;a href=&quot;mailto:server@openvas.service&quot;&gt;server@openvas.service&lt;/a&gt;&quot;&quot;&gt;redis-server&amp;#64;openvas.service&lt;/a&gt;&lt;br&gt;sudo systemctl enable &lt;a href=&quot;mailto:redis-&lt;a href=&quot;mailto:server@openvas.service&quot;&gt;server@openvas.service&lt;/a&gt;&quot;&quot;&gt;redis-server&amp;#64;openvas.service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;sudo usermod -aG redis gvm&lt;/p&gt;
&lt;p&gt;  配置 Mosquitto MQTT&lt;/p&gt;
&lt;p&gt;sudo apt install -y mosquitto&lt;/p&gt;
&lt;p&gt;sudo systemctl start mosquitto.service&lt;br&gt;sudo systemctl enable mosquitto.service&lt;br&gt;echo “mqtt_server_uri = localhost:1883” | sudo tee -a /etc/openvas/openvas.conf&lt;/p&gt;
&lt;p&gt;配置服务的权限&lt;/p&gt;
&lt;p&gt;sudo mkdir -p /var/lib/notus&lt;br&gt;sudo mkdir -p /run/gvmd&lt;/p&gt;
&lt;p&gt;sudo chown -R gvm:gvm /var/lib/gvm&lt;br&gt;sudo chown -R gvm:gvm /var/lib/openvas&lt;br&gt;sudo chown -R gvm:gvm /var/lib/notus&lt;br&gt;sudo chown -R gvm:gvm /var/log/gvm&lt;br&gt;sudo chown -R gvm:gvm /run/gvmd&lt;/p&gt;
&lt;p&gt;sudo chmod -R g+srw /var/lib/gvm&lt;br&gt;sudo chmod -R g+srw /var/lib/openvas&lt;br&gt;sudo chmod -R g+srw /var/log/gvm&lt;/p&gt;
&lt;p&gt;sudo chown gvm:gvm /usr/local/sbin/gvmd&lt;br&gt;sudo chmod 6750 /usr/local/sbin/gvmd&lt;/p&gt;
&lt;p&gt;sudo chown gvm:gvm /usr/local/bin/greenbone-nvt-sync&lt;br&gt;sudo chmod 740 /usr/local/sbin/greenbone-feed-sync&lt;br&gt;sudo chown gvm:gvm /usr/local/sbin/greenbone-&lt;em&gt;-sync&lt;br&gt;sudo chmod 740 /usr/local/sbin/greenbone-&lt;/em&gt;-sync&lt;/p&gt;
&lt;p&gt;export GNUPGHOME=/tmp/openvas-gnupg&lt;br&gt;mkdir -p $GNUPGHOME&lt;/p&gt;
&lt;p&gt;gpg –import /tmp/GBCommunitySigningKey.asc&lt;br&gt;gpg –import-ownertrust &amp;lt; /tmp/ownertrust.txt&lt;/p&gt;
&lt;p&gt;export OPENVAS_GNUPG_HOME=/etc/openvas/gnupg&lt;br&gt;sudo mkdir -p $OPENVAS_GNUPG_HOME&lt;br&gt;sudo cp -r /tmp/openvas-gnupg/* $OPENVAS_GNUPG_HOME/&lt;br&gt;sudo chown -R gvm:gvm $OPENVAS_GNUPG_HOME&lt;/p&gt;
&lt;p&gt;现在，键入 sudo visudo 并将以下行放在文件末尾：&lt;/p&gt;
&lt;h1 id=&quot;h1-allow-users-of-the-gvm-group-run-openvas&quot;&gt;&lt;a name=&quot;allow users of the gvm group run openvas&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;allow users of the gvm group run openvas&lt;/h1&gt;&lt;p&gt;%gvm ALL = NOPASSWD: /usr/local/sbin/openvas&lt;/p&gt;
&lt;p&gt;配置 PostgreSQL（确保在第三个命令:D 将用户 &amp;gt; 的 &amp;lt;name 替换为您的用户名）&lt;/p&gt;
&lt;p&gt;sudo apt install -y postgresql&lt;/p&gt;
&lt;p&gt;sudo systemctl start postgresql&lt;a href=&quot;https://github.com/14&quot; title=&quot;&amp;#64;14&quot; class=&quot;at-link&quot;&gt;@14&lt;/a&gt;-main&lt;/p&gt;
&lt;p&gt;sudo chmod og+rX /home /home/&amp;lt;name of your user&amp;gt;&lt;/p&gt;
&lt;p&gt;sudo -u postgres bash&lt;/p&gt;
&lt;p&gt;createuser -DRS gvm&lt;/p&gt;
&lt;p&gt;createdb -O gvm gvmd&lt;/p&gt;
&lt;p&gt;exit&lt;/p&gt;
&lt;p&gt;sudo -u postgres bash&lt;/p&gt;
&lt;p&gt;psql gvmd&lt;/p&gt;
&lt;p&gt;create role dba with superuser noinherit;&lt;/p&gt;
&lt;p&gt;grant dba to gvm;&lt;/p&gt;
&lt;p&gt;exit&lt;/p&gt;
&lt;p&gt;exit&lt;/p&gt;
&lt;p&gt;配置 GVM 用户名和密码（确保在 &amp;lt;password&amp;gt; 字段中键入强密码）&lt;/p&gt;
&lt;p&gt;gvmd –create-user=admin –password=&amp;lt;password&amp;gt;&lt;/p&gt;
&lt;p&gt;  配置 Feed 导入&lt;/p&gt;
&lt;p&gt;gvmd –modify-setting 78eceaec-3385-11ea-b237-28d24461215b –value &lt;code&gt;gvmd --get-users --verbose | grep admin | awk &amp;#39;{print $2}&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;为系统守护程序配置服务：&lt;/p&gt;
&lt;p&gt;使用&lt;/p&gt;
&lt;p&gt;vim $BUILD_DIR/ospd-openvas.service&lt;/p&gt;
&lt;p&gt;并粘贴以下行以配置 OSPD-OpenVAS：&lt;/p&gt;
&lt;p&gt;[Unit]&lt;br&gt;Description=OSPd Wrapper for the OpenVAS Scanner (ospd-openvas)&lt;br&gt;Documentation=man:ospd-openvas(8) man:openvas(8)&lt;br&gt;After=network.target networking.service &lt;a href=&quot;mailto:redis-&lt;a href=&quot;mailto:server@openvas.service&quot;&gt;server@openvas.service&lt;/a&gt;&quot;&quot;&gt;redis-server&amp;#64;openvas.service&lt;/a&gt;&lt;br&gt;Wants=&lt;a href=&quot;mailto:redis-&lt;a href=&quot;mailto:server@openvas.service&quot;&gt;server@openvas.service&lt;/a&gt;&quot;&quot;&gt;redis-server&amp;#64;openvas.service&lt;/a&gt;&lt;br&gt;ConditionKernelCommandLine=!recovery&lt;/p&gt;
&lt;p&gt;[Service]&lt;br&gt;Type=forking&lt;br&gt;User=gvm&lt;br&gt;Group=gvm&lt;br&gt;RuntimeDirectory=ospd&lt;br&gt;RuntimeDirectoryMode=2775&lt;br&gt;PIDFile=/run/ospd/ospd-openvas.pid&lt;br&gt;ExecStart=/usr/local/bin/ospd-openvas –unix-socket /run/ospd/ospd-openvas.sock –pid-file /run/ospd/ospd-openvas.pid –log-file /var/log/gvm/ospd-openvas.log –lock-file-dir /var/lib/openvas –socket-mode 0o770 –mqtt-broker-address localhost –mqtt-broker-port 1883 –notus-feed-dir /var/lib/notus/advisories&lt;br&gt;SuccessExitStatus=SIGKILL&lt;br&gt;Restart=always&lt;br&gt;RestartSec=60&lt;/p&gt;
&lt;p&gt;[Install]&lt;br&gt;WantedBy=multi-user.target&lt;/p&gt;
&lt;p&gt;现在将服务配置复制到系统目录&lt;/p&gt;
&lt;p&gt;sudo cp $BUILD_DIR/ospd-openvas.service /etc/systemd/system/&lt;/p&gt;
&lt;p&gt;使用&lt;/p&gt;
&lt;p&gt;vim $BUILD_DIR/notus-scanner.service&lt;/p&gt;
&lt;p&gt;并粘贴以下行以配置 notus-scanner：&lt;/p&gt;
&lt;p&gt;[Unit]&lt;br&gt;Description=Notus Scanner&lt;br&gt;Documentation=&lt;a href=&quot;https://github.com/greenbone/notus-scanner&quot;&gt;https://github.com/greenbone/notus-scanner&lt;/a&gt;&lt;br&gt;After=mosquitto.service&lt;br&gt;Wants=mosquitto.service&lt;br&gt;ConditionKernelCommandLine=!recovery&lt;/p&gt;
&lt;p&gt;[Service]&lt;br&gt;Type=forking&lt;br&gt;User=gvm&lt;br&gt;RuntimeDirectory=notus-scanner&lt;br&gt;RuntimeDirectoryMode=2775&lt;br&gt;PIDFile=/run/notus-scanner/notus-scanner.pid&lt;br&gt;ExecStart=/usr/local/bin/notus-scanner –products-directory /var/lib/notus/products –log-file /var/log/gvm/notus-scanner.log&lt;br&gt;SuccessExitStatus=SIGKILL&lt;br&gt;Restart=always&lt;br&gt;RestartSec=60&lt;/p&gt;
&lt;p&gt;[Install]&lt;br&gt;WantedBy=multi-user.target&lt;/p&gt;
&lt;p&gt;现在将服务配置复制到系统目录&lt;/p&gt;
&lt;p&gt;sudo cp $BUILD_DIR/notus-scanner.service /etc/systemd/system/&lt;/p&gt;
&lt;p&gt;使用 打开 gvmd.service 文件&lt;/p&gt;
&lt;p&gt;vim $BUILD_DIR/gvmd.service&lt;/p&gt;
&lt;p&gt;并粘贴以下行以配置 GVMD：&lt;/p&gt;
&lt;p&gt;[Unit]&lt;br&gt;Description=Greenbone Vulnerability Manager daemon (gvmd)&lt;br&gt;After=network.target networking.service postgresql.service ospd-openvas.service&lt;br&gt;Wants=postgresql.service ospd-openvas.service&lt;br&gt;Documentation=man:gvmd(8)&lt;br&gt;ConditionKernelCommandLine=!recovery&lt;/p&gt;
&lt;p&gt;[Service]&lt;br&gt;Type=forking&lt;br&gt;User=gvm&lt;br&gt;Group=gvm&lt;br&gt;PIDFile=/run/gvmd/gvmd.pid&lt;br&gt;RuntimeDirectory=gvmd&lt;br&gt;RuntimeDirectoryMode=2775&lt;br&gt;ExecStart=/usr/local/sbin/gvmd –osp-vt-update=/run/ospd/ospd-openvas.sock –listen-group=gvm&lt;br&gt;Restart=always&lt;br&gt;TimeoutStopSec=10&lt;/p&gt;
&lt;p&gt;[Install]&lt;br&gt;WantedBy=multi-user.target&lt;/p&gt;
&lt;p&gt;现在将服务配置复制到系统目录&lt;/p&gt;
&lt;p&gt;sudo cp $BUILD_DIR/gvmd.service /etc/systemd/system/&lt;/p&gt;
&lt;p&gt;使用 打开 gsad.service 文件&lt;/p&gt;
&lt;p&gt;vim $BUILD_DIR/gsad.service&lt;/p&gt;
&lt;p&gt;并粘贴以下行以配置 GSAD：&lt;/p&gt;
&lt;p&gt;[Unit]&lt;br&gt;Description=Greenbone Security Assistant daemon (gsad)&lt;br&gt;Documentation=man:gsad(8) &lt;a href=&quot;https://www.greenbone.net&quot;&gt;https://www.greenbone.net&lt;/a&gt;&lt;br&gt;After=network.target gvmd.service&lt;br&gt;Wants=gvmd.service&lt;/p&gt;
&lt;p&gt;[Service]&lt;br&gt;Type=exec&lt;br&gt;User=gvm&lt;br&gt;Group=gvm&lt;br&gt;RuntimeDirectory=gsad&lt;br&gt;RuntimeDirectoryMode=2775&lt;br&gt;PIDFile=/run/gsad/gsad.pid&lt;br&gt;ExecStart=/usr/local/sbin/gsad –foreground –listen=127.0.0.1 –port=9392 –http-only&lt;br&gt;Restart=always&lt;br&gt;TimeoutStopSec=10&lt;/p&gt;
&lt;p&gt;[Install]&lt;br&gt;WantedBy=multi-user.target&lt;br&gt;Alias=greenbone-security-assistant.service&lt;/p&gt;
&lt;p&gt;现在将服务配置复制到系统目录&lt;/p&gt;
&lt;p&gt;sudo cp $BUILD_DIR/gsad.service /etc/systemd/system/&lt;/p&gt;
&lt;p&gt;使用以下命令激活所有服务：&lt;/p&gt;
&lt;p&gt;sudo systemctl daemon-reload&lt;/p&gt;
&lt;p&gt;使用以下命令启用所有服务，以便每次都不需要手动启动它们：&lt;/p&gt;
&lt;p&gt;sudo systemctl enable notus-scanner&lt;/p&gt;
&lt;p&gt;sudo systemctl enable ospd-openvas&lt;/p&gt;
&lt;p&gt;sudo systemctl enable gvmd&lt;/p&gt;
&lt;p&gt;sudo systemctl enable gsad&lt;/p&gt;
&lt;p&gt;使用以下命令同步 NVT 源（尽管互联网速度很好，但这可能需要很多时间）。如果你在机构中进行这项设置，请确保要求网络团队为你的系统打开 rsync 端口，因为它很可能会被关闭。Rsync 通常在端口 873 上运行。&lt;/p&gt;
&lt;p&gt;sudo -u gvm greenbone-nvt-sync&lt;/p&gt;
&lt;p&gt;使用以下命令下载 SCAP、CERT 和 GVMD 数据，确保一一使用这些命令（尽管互联网速度很好，这可能需要很多时间）：&lt;/p&gt;
&lt;p&gt;sudo -u gvm greenbone-feed-sync –type SCAP&lt;/p&gt;
&lt;p&gt;sudo -u gvm greenbone-feed-sync –type CERT&lt;/p&gt;
&lt;p&gt;sudo -u gvm greenbone-feed-sync –type GVMD_DATA&lt;/p&gt;
&lt;p&gt;  启动所有服务&lt;/p&gt;
&lt;p&gt;sudo systemctl start notus-scanner&lt;/p&gt;
&lt;p&gt;sudo systemctl start ospd-openvas&lt;/p&gt;
&lt;p&gt;sudo systemctl start gvmd&lt;/p&gt;
&lt;p&gt;sudo systemctl start gsad&lt;/p&gt;
</description><pubDate>Mon, 19 May 2025 17:22:33 +0800</pubDate></item><item><title>虚拟化技术介绍</title><link>http://152.136.151.227/?id=18</link><description>&lt;h1 id=&quot;h1-u865Au62DFu5316u6280u672Fu4ECBu7ECD&quot;&gt;&lt;a name=&quot;虚拟化技术介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;虚拟化技术介绍&lt;/h1&gt;&lt;h2 id=&quot;h2-u6781u7B80u4ECBu7ECD&quot;&gt;&lt;a name=&quot;极简介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;极简介绍&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;对于我们想要虚拟化的对象&lt;/strong&gt;，提供&lt;strong&gt;实际资源&lt;/strong&gt;之上的抽象。应用不同抽象级别将会呈现不同的虚拟化技术。&lt;/p&gt;
&lt;p&gt;基于抽象级别的虚拟化技术有两类最为常用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基于虚拟机(VM)：虚拟化整个操作系统，换句话说是虚拟化完整的ISA&lt;/li&gt;&lt;li&gt;基于容器(Container)&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id=&quot;h2-hypervisors&quot;&gt;&lt;a name=&quot;Hypervisors&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Hypervisors&lt;/h2&gt;&lt;p&gt;用于虚拟化的特殊软件通称，其本身有两个部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Virtual Machine Monitor(VMM)：捕获和模拟特权指令集(仅操作系统内内核可以运行)&lt;/li&gt;&lt;li&gt;Device model：设备模型，用于虚拟化I/O设备&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;h3-vmm&quot;&gt;&lt;a name=&quot;VMM&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;VMM&lt;/h3&gt;&lt;p&gt;硬件在绝大多数情况下不能直接在虚拟机上使用，因此需要通过VMM捕获硬件(磁盘、网卡…)的特权指令，并代表虚拟机执行这些指令。其需满足三个属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;隔离性：将guest(VMs虚拟机)彼此进行隔离&lt;/li&gt;&lt;li&gt;等效性：有没有使用虚拟化，对于硬件角度来说执行表现应当相同；即没有在翻译的情况下&lt;strong&gt;在硬件&lt;/strong&gt;执行(几乎所有的)指令&lt;/li&gt;&lt;li&gt;性能：有与没有虚拟机的情况下性能应做到(几乎)一致，即虚拟机的开销应尽可能的小&lt;/li&gt;&lt;/ul&gt;
&lt;h4 id=&quot;h4-u529Fu80FD&quot;&gt;&lt;a name=&quot;功能&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;功能&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;不能访问特权级，&lt;code&gt;VMM&lt;/code&gt;应截获这些请求并模拟特权级调用&lt;/li&gt;&lt;li&gt;异常处理和中断&lt;/li&gt;&lt;li&gt;大部分cpu指令&lt;strong&gt;直接在物理机CPU上运行&lt;/strong&gt;，仅在陷入某些特权指令才使用虚拟化CPU(运行效率基本与在物理机一致)&lt;/li&gt;&lt;li&gt;I/O的地址映射&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-u5185u5B58u865Au62DFu5316&quot;&gt;&lt;a name=&quot;内存虚拟化&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;内存虚拟化&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/9832140/what-exactly-do-shadow-page-tables-for-vmms-do&quot;&gt;影子页表&lt;/a&gt;&lt;/li&gt;&lt;li&gt;硬件支持&lt;a href=&quot;https://royhunter.github.io/2014/06/18/KVM-EPT/&quot;&gt;EPT&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-cpu-&quot;&gt;&lt;a name=&quot;CPU虚拟化&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;CPU虚拟化&lt;/h2&gt;&lt;p&gt;见&lt;a href=&quot;https://xinsheng.huawei.com/cn/index.php?app=forum&amp;mod=Detail&amp;act=index&amp;id=7715651&quot;&gt;这篇文章&lt;/a&gt;，对虚拟化特权级进行了全面解释。&lt;/p&gt;
&lt;p&gt;代码定位&lt;a href=&quot;https://zhuanlan.zhihu.com/p/311192204&quot;&gt;见此&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u5168u865Au62DFu5316u4E0Eu534Au865Au62DFu5316&quot;&gt;&lt;a name=&quot;全虚拟化与半虚拟化&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;全虚拟化与半虚拟化&lt;/h2&gt;&lt;p&gt;全虚拟化中，客户OS(guest OS)“不知道”自己运行在虚拟环境中，它的运行状态和在物理机中相同；而半虚拟化状态中，guest OS对虚拟环境做了特化，I/O的系统调用会被hypercalls替换掉。&lt;/p&gt;
&lt;p&gt;它们的结构区别如下图所示：&lt;br&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230803000233.png&quot; alt=&quot;20230803000233&quot;&gt;&lt;/p&gt;
&lt;p&gt;半虚拟化状态中，guest os的驱动程序被称为&lt;code&gt;前端驱动程序&lt;/code&gt;，主机的被称为&lt;code&gt;后端驱动程序&lt;/code&gt;，这种前后端的实现方式很大的提高了交互效率，具体见&lt;a href=&quot;https://www.openeuler.org/zh/blog/yorifang/virtio-spec-overview.html&quot;&gt;virtio&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;对于I/O虚拟化，参见&lt;a href=&quot;https://learn.microsoft.com/en-us/windows-hardware/drivers/network/overview-of-single-root-i-o-virtualization--sr-iov-&quot;&gt;sriov&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-hypervisors-&quot;&gt;&lt;a name=&quot;Hypervisors介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Hypervisors介绍&lt;/h2&gt;&lt;p&gt;INTEL有两种虚拟化风格：&lt;code&gt;Vt-x&lt;/code&gt;和&lt;code&gt;Vt-i&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vt-x：适用于Intel x86 32或64位架构&lt;/li&gt;&lt;li&gt;Vt-i：适用于安腾处理器系列&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;本节将更为熟悉的Vt-x指令集&lt;/p&gt;
&lt;h3 id=&quot;h3-vt-x-&quot;&gt;&lt;a name=&quot;VT-x指令集&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;VT-x指令集&lt;/h3&gt;&lt;p&gt;物理机中，执行顺序是程序指令-&amp;gt;CPU指令；&lt;br&gt;而在虚拟机中，执行顺序是程序指令-&amp;gt;虚拟CPU指令-&amp;gt;CPU指令。&lt;br&gt;这将导致指令翻译两次，会造成巨大开销(详见&lt;a href=&quot;http://hardwaresecrets.com/everything-you-need-to-know-about-the-intel-virtualization-technology/&quot;&gt;这篇文章&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;通过抽象CPU指令到虚拟指令，即对CPU指令扩充一些虚拟专用指令，可以在虚拟机完成：程序指令-&amp;gt;CPU指令&lt;/p&gt;
&lt;p&gt;对于Vt-x来说，它还做了一些权限分割上的工作，具体可见&lt;a href=&quot;https://security.stackexchange.com/questions/129098/what-is-protection-ring-1&quot;&gt;这篇关于ring -1的回答&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;细节了解和代码定位，参考&lt;a href=&quot;https://jhinxs.com/intel-vt-x-mini-vt-%E6%A1%86%E6%9E%B6%E7%9A%84%E5%AE%9E%E7%8E%B0/&quot;&gt;这篇博客&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-kvm-&quot;&gt;&lt;a name=&quot;KVM创建虚拟机&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;KVM创建虚拟机&lt;/h3&gt;&lt;p&gt;在用户态中创建虚拟机的过程如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建一个裸VM&lt;/li&gt;&lt;li&gt;映射VM的用户空间内存&lt;/li&gt;&lt;li&gt;创建VCPU/IRQCHIP，并映射vt-x指令集&lt;/li&gt;&lt;li&gt;其他硬件配置：寄存器、FPU、LAPIC等&lt;/li&gt;&lt;li&gt;启动VM&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;具体信息和代码定位详见&lt;a href=&quot;https://www.linux-kvm.org/page/Documents#Documentation&quot;&gt;KVM官网相关文档&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3--vhost-&quot;&gt;&lt;a name=&quot;基于vhost的数据交互&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;基于vhost的数据交互&lt;/h3&gt;&lt;p&gt;这里以一个vhost-net设备的生命周期为例。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230808001723.png&quot; alt=&quot;20230808001723&quot;&gt;&lt;/p&gt;
&lt;p&gt;该设备初始化时，会为QEMU对应进程创建一个内核线程，专门处理guest I/O，该线程侦听主机端&lt;code&gt;virtqueues&lt;/code&gt;上的事件。&lt;/p&gt;
&lt;p&gt;事件为传输时，guest上的TX(传输)队列排出(virtio术语叫kick)数据包，线程将该包放到抽头设备(tap)，后继续使用正常底层网络设备(路由、交换机)等进行常规网络包传输工作；接收(RX)同理。&lt;/p&gt;
&lt;p&gt;事件注册采用&lt;code&gt;eventfd&lt;/code&gt;机制，这是文件描述符，具体功能和机制参见&lt;a href=&quot;https://zhuanlan.zhihu.com/p/40572954&quot;&gt;这篇博客&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&quot;h2-u5176u4ED6u865Au62DFu5316u5C1Du8BD5&quot;&gt;&lt;a name=&quot;其他虚拟化尝试&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;其他虚拟化尝试&lt;/h2&gt;&lt;h3 id=&quot;h3-unikernel&quot;&gt;&lt;a name=&quot;Unikernel&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Unikernel&lt;/h3&gt;&lt;p&gt;作为虚拟化技术的一种尝试，基础思想就是；仅将应用所需的环境包装到虚拟环境中，即一个虚拟机完成单一的应用功能。好处显然易见——轻量、安全、快速。但是单一的应用和复杂的打包机制也成为制约unikernel不利条件。&lt;/p&gt;
&lt;p&gt;其基础概念可以查看&lt;a href=&quot;http://unikernel.org/&quot;&gt;官网&lt;/a&gt;&lt;br&gt;与容器的比较可以参考&lt;a href=&quot;https://phoenixnap.com/kb/unikernel-vs-container&quot;&gt;这篇博客&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-project-dune&quot;&gt;&lt;a name=&quot;Project-Dune&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Project-Dune&lt;/h3&gt;&lt;p&gt;斯坦福大学设计的一种机制，可以通过虚拟化技术让用户程序跑在&lt;code&gt;ring 0&lt;/code&gt;中，即在非特权的上下文中执行特权指令。&lt;/p&gt;
&lt;p&gt;原理可用一张图表示：&lt;br&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230810235726.png&quot; alt=&quot;20230810235726&quot;&gt;&lt;/p&gt;
&lt;p&gt;代码被分为受信任部分和非受信任部分，它们都运行在同一个物理地址上，但受信任的代码所在页被&lt;code&gt;hypervisor bits&lt;/code&gt;位标记保护。受信任的代码通过Dune进程(由&lt;code&gt;libdune库提供&lt;/code&gt;)运行在ring 0，非受信任的代码运行在ring 3。&lt;/p&gt;
&lt;p&gt;详细信息可查阅&lt;a href=&quot;http://dune.scs.stanford.edu/&quot;&gt;project-dune官网&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-novm&quot;&gt;&lt;a name=&quot;novm&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;novm&lt;/h3&gt;&lt;p&gt;在VM中提供了一个文件系统，而非块设备。是一种虚拟机的轻量化实现。&lt;/p&gt;
&lt;p&gt;具体可见&lt;a href=&quot;https://github.com/google/novm&quot;&gt;github项目&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u5BB9u5668&quot;&gt;&lt;a name=&quot;容器&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;容器&lt;/h2&gt;&lt;p&gt;Linux容器有三个组成基础：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;namesapce：Linux资源的可见性&lt;/li&gt;&lt;li&gt;cgroups：资源配额控制&lt;/li&gt;&lt;li&gt;文件分层系统：容器的文件系统，实现内存和磁盘的共享&lt;/li&gt;&lt;/ul&gt;
&lt;h3 id=&quot;h3-namespace&quot;&gt;&lt;a name=&quot;Namespace&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Namespace&lt;/h3&gt;&lt;p&gt;命名空间是Linux中的一种进程的逻辑隔离技术，即缩小进程的可见性。对于namespace的进程来说，它看不到除自己namespace外的其他资源。&lt;/p&gt;
&lt;p&gt;namespace有很多类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UTS&lt;/li&gt;&lt;li&gt;PID&lt;/li&gt;&lt;li&gt;Mount&lt;/li&gt;&lt;li&gt;Network&lt;/li&gt;&lt;li&gt;IPC&lt;/li&gt;&lt;li&gt;cgroup&lt;/li&gt;&lt;li&gt;time&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;其详情介绍可以参考&lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_namespaces&quot;&gt;wiki&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原理分析和用法可以参考&lt;a href=&quot;https://blog.quarkslab.com/digging-into-linux-namespaces-part-1.html&quot;&gt;这篇博客&lt;/a&gt;，这大哥的博客写的是真好，从实践到原理到源码介绍的非常细致。如果有时间推荐两部分都看一下。&lt;/p&gt;
&lt;h3 id=&quot;h3-cgroup&quot;&gt;&lt;a name=&quot;Cgroup&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Cgroup&lt;/h3&gt;&lt;p&gt;cgroups（Control Group）是一项 Linux 内核功能，用于限制、说明和隔离进程集合的资源使用情况（CPU、内存、磁盘 I/O 等 ）&lt;br&gt;有两个版本，v1(2.6.24)和v2(4.5)。&lt;/p&gt;
&lt;p&gt;v2的版本介绍可以参考&lt;a href=&quot;https://en.wikipedia.org/wiki/Cgroups&quot;&gt;wiki百科&lt;/a&gt;和&lt;a href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;kernel官方文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;v1的版本介绍可以参考&lt;a href=&quot;https://docs.kernel.org/admin-guide/cgroup-v1/cgroups.html&quot;&gt;kernel官方文档&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u5206u5C42u6587u4EF6u7CFBu7EDF&quot;&gt;&lt;a name=&quot;分层文件系统&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;分层文件系统&lt;/h3&gt;&lt;h4 id=&quot;h4-u6587u4EF6u7CFBu7EDF&quot;&gt;&lt;a name=&quot;文件系统&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;文件系统&lt;/h4&gt;&lt;p&gt;Linux的设计理念是“万物均文件”，即系统中所有对象均使用文件进行抽象，访问这些对象和访问文件的过程是一致的(包括块文件和非块文件)。&lt;/p&gt;
&lt;p&gt;Linux使用虚拟文件系统(VFS)层抽象所有文件系统。所有文件系统均在VFS中注册。其具有以下重要的数据结构：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文件&lt;/li&gt;&lt;li&gt;INODE&lt;/li&gt;&lt;li&gt;目录项&lt;/li&gt;&lt;li&gt;超级块&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;详细内容可以参考&lt;a href=&quot;https://wushifublog.com/2020/05/22/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Linux%E5%86%85%E6%A0%B8%E2%80%94%E2%80%94VFS/&quot;&gt;这篇文章&lt;/a&gt;，和&lt;a href=&quot;https://www.zhihu.com/column/c_1108400140804726784&quot;&gt;这个专栏系列中文件系统部分&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-u4F2Au6587u4EF6u7CFBu7EDF&quot;&gt;&lt;a name=&quot;伪文件系统&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;伪文件系统&lt;/h4&gt;&lt;p&gt;对于一些非块文件如&lt;code&gt;procfs&lt;/code&gt;，它们可能通过文件接口公开内核的的一些资源，这些文件系统被称为&lt;code&gt;伪文件系统&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;可参考&lt;a href=&quot;https://superuser.com/questions/1198292/what-is-a-pseudo-file-system-in-linux&quot;&gt;论坛回答&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-u5206u5C42u6587u4EF6u7CFBu7EDFu7B80u4ECB&quot;&gt;&lt;a name=&quot;分层文件系统简介&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;分层文件系统简介&lt;/h4&gt;&lt;p&gt;在上述Linux文件系统中，有两件事是容器需要但其无法满足的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内存共享&lt;/li&gt;&lt;li&gt;磁盘空间共享&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;在分层文件系统中，文件系统被分成多层，&lt;strong&gt;每层都是只读文件系统&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这些层在同意主机上的容器之间共享，且&lt;strong&gt;inode是相同的&lt;/strong&gt;，它们将会引用相同操作系统页面进行缓存。&lt;/p&gt;
&lt;p&gt;下面将介绍两种Linux中正在使用的分层文件系统。&lt;/p&gt;
&lt;h4 id=&quot;h4-unionfs-ufs-&quot;&gt;&lt;a name=&quot;unionfs(UFS)&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;unionfs(UFS)&lt;/h4&gt;&lt;p&gt;unionfs允许管理员将文件在物理上分开，但在逻辑上合并到单个视图中。&lt;/p&gt;
&lt;p&gt;合并目录的集合称为联合(黄色部分)，每个物理目录称为分支(蓝色部分)。&lt;br&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230815004314.png&quot; alt=&quot;20230815004314&quot;&gt;&lt;/p&gt;
&lt;p&gt;每个分支都分配有一个优先级。具有较高优先级的分支会覆盖具有较低优先级的分支。 Unionfs 对目录进行操作。如果一个目录存在于两个底层分支中，则Unionfs目录的内容和属性是两个较低目录的组合。 Unionfs 自动删除任何重复的目录条目，因此用户不会因重复的文件名或目录而感到困惑。如果一个文件存在于两个分支中，则Unionfs文件的内容和属性与高优先级分支中的文件相同，而低优先级分支中的文件被忽略。&lt;/p&gt;
&lt;p&gt;需要注意的是，当多个同名文件挂载到同联合中时，&lt;strong&gt;默认&lt;/strong&gt;复制第一个文件中的内容。&lt;/p&gt;
&lt;p&gt;测试：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ ls /Fruits
Tomato hi/
$ ls /Veg
Tomato

$ cat /Fruits/Tomato
I am botanically a fruit.
$ cat /Veg/Tomato
I am horticulturally a veg.

# 联合目录挂载到 Eat
$ mount -t overlay -o dirs=/Fruits:/Veg overlay /Eat

# 查看Tomato的内容
$ cat /Eat/Tomato
I am botanically a fruit.

# 查看目录合并结果
$ ls /Eat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;unionfs包括aufs均已过时，现在基本都用&lt;code&gt;overlay&lt;/code&gt;或&lt;code&gt;overlay2&lt;/code&gt;作为容器的文件系统。&lt;/p&gt;
&lt;p&gt;参考如下链接：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linuxjournal.com/article/7714&quot;&gt;祖宗：2004年的Linux期刊&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.jianshu.com/p/3ba255463047&quot;&gt;原理剖析+源码解读&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://medium.com/&lt;a href=&quot;https://github.com/knoldus&quot; title=&quot;&amp;#64;knoldus&quot; class=&quot;at-link&quot;&gt;@knoldus&lt;/a&gt;/unionfs-a-file-system-of-a-container-2136cd11a779&quot;&gt;直观图片+完整实验&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-overlayfs&quot;&gt;&lt;a name=&quot;Overlayfs&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;Overlayfs&lt;/h4&gt;&lt;p&gt;Linux 3.18内核版本之后，overlayfs被集成进内核。&lt;/p&gt;
&lt;p&gt;其作用是&lt;strong&gt;将一个目录地内容覆盖到另一个目录上&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当前有两个版本：v1和v2&lt;br&gt;v1有两层:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lower：只读层&lt;/li&gt;&lt;li&gt;upper：读写层&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;规则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当进程“读取”文件时，overlayfs文件系统驱动将优先在上层目录upperdir中查找并从该目录中读取文件，找不到则在下层目录lowerdir中查找。&lt;/li&gt;&lt;li&gt;当进程”写入”文件时，overlayfs会将其写入上层目录upperdir。&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;v2有三层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;base: 基础层，创建时初始化，是只读层&lt;/li&gt;&lt;li&gt;overlay: 提供从基本层的可见性，当基础层文件发生更改，则存储到其下一层&lt;/li&gt;&lt;li&gt;diff: 在overlay做的更改存储于此。基础层的任何文件/目录更改都会将文件从基础层复制到diff层，然后将更改写入diff层&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;v2示例：&lt;/p&gt;
&lt;h5 id=&quot;h5-u521Du59CBu5316u521Bu5EFA&quot;&gt;&lt;a name=&quot;初始化创建&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;初始化创建&lt;/h5&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;root@instance-1: mkdir base diff overlay workdir 
root@instance-1: echo &amp;quot;test data&amp;quot; &amp;gt; base/test1 
root@instance-1: sudo mount \ &amp;gt; -t overlay \ 
&amp;gt; -o lowerdir=base,upperdir=diff,workdir=workdir \ 
&amp;gt; overlay \ 
&amp;gt; overlay&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;过程和上一节一致，不做赘述。&lt;/p&gt;
&lt;h5 id=&quot;h5--overlay&quot;&gt;&lt;a name=&quot;修改overlay&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;修改overlay&lt;/h5&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;root@instance-1:/overlay# touch test2 
root@instance-1:/overlay# ls test1 
test2 
root@instance-1:-/overlay# cd ../diff 
root@instance-1:-/diff# ls 
test2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可见修改的结果在diff中可见&lt;/p&gt;
&lt;p&gt;可以动手试试修改文件内容，看在overlay和base中如何变化&lt;/p&gt;
&lt;p&gt;参考&lt;a href=&quot;https://www.cnblogs.com/FengZeng666/p/14173906.html&quot;&gt;这篇博客&lt;/a&gt;&lt;/p&gt;
</description><pubDate>Sun, 14 Jul 2024 20:09:20 +0800</pubDate></item><item><title>Dfi：一个面向大规模代码库的过程间价值流分析框架</title><link>http://152.136.151.227/?id=17</link><description>&lt;h2 id=&quot;h2-u89E3u51B3u75DBu70B9&quot;&gt;&lt;a name=&quot;解决痛点&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;解决痛点&lt;/h2&gt;&lt;p&gt;由于内存和运行时需求较高，目前的价值流计算方法无法扩展到大型代码库。&lt;/p&gt;
&lt;h2 id=&quot;h2-u4EF7u503Cu6D41u5206u6790&quot;&gt;&lt;a name=&quot;价值流分析&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;价值流分析&lt;/h2&gt;&lt;p&gt;价值流分析是数据流分析的一个子集，它有助于静态地分析变量和内存块等程序结构之间的依赖关系。它支持许多关键的程序分析技术，这些技术被广泛用于编译器优化和寻找安全漏洞：指向分析、空指针分析和污点分析。为了有效地操作，这类技术通常需要精确的价值流信息，这些信息具有上下文和流敏感以及过程间性。” &amp;lt;span class=&amp;quot;citation&amp;quot; data-citation=&amp;quot;%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F8438660%2Fitems%2FMZGEWCFE%22%5D%2C%22locator%22%3A%221%22%7D%5D%2C%22properties%22%3A%7B%7D%7D&amp;quot; ztype=&amp;quot;zcitation&amp;quot;&amp;gt;(&amp;lt;span class=&amp;quot;citation-item&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;zotero://select/library/items/MZGEWCFE&amp;quot;&amp;gt;Hsu 等, 2022, p. 1&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;)&amp;lt;/span&amp;gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u521Bu65B0u70B9&quot;&gt;&lt;a name=&quot;创新点&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;创新点&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;开发一种新的图结构，采用LLVM IR扩展，多了两个操作，简化指针混淆的建模&lt;/li&gt;&lt;li&gt;由上个方式产生的用于价值流分析的def-use链的轻量级和精确的稀疏表示，包含顶层变量和获取地址的变量&lt;/li&gt;&lt;li&gt;一个通过图可达性求解价值流的算法，该算法的规模几乎与处理的顶点数量成线性关系，需要的内存显著减少，而且显著快于以前的解决方案&lt;/li&gt;&lt;li&gt;基于LLVM IR，可扩展到包含数十万行代码的大型现实项目&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2-dfi-&quot;&gt;&lt;a name=&quot;DFI 设计与实现&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;DFI 设计与实现&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;attachments/77NCYF4F.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;77NCYF4F&amp;quot; width=&amp;quot;514&amp;quot; height=&amp;quot;271&amp;quot; src=&amp;quot;attachments/77NCYF4F.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;p&gt;DFI主要包括两个主要组成部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主分析引擎&lt;/li&gt;&lt;li&gt;客户端分析&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;首先，分析引擎基于客户端提供的价值流映射信息计算得到运行过程内的DFT间隔；&lt;img src=&quot;attachments/SZWRTZMH.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;SZWRTZMH&amp;quot; width=&amp;quot;516&amp;quot; height=&amp;quot;273&amp;quot; src=&amp;quot;attachments/SZWRTZMH.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;p&gt;其次，过程内的价值流被传递到它们的调用者以支持过程间查询；&lt;/p&gt;
&lt;p&gt;最后，客户端分析将受到流和上下文敏感的价值流结果，以解决其领域特定的作用&lt;/p&gt;
&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;预处理：修改了两个操作&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;预处理：修改了两个操作&lt;/h3&gt;&lt;p&gt;dfi.store：将更新的存储量用不同的标记存储，使得可以用跟踪标量值相同的方法跟踪强更新的内存依赖&lt;img src=&quot;attachments/8IEUGXVH.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;8IEUGXVH&amp;quot; width=&amp;quot;501&amp;quot; height=&amp;quot;420&amp;quot; src=&amp;quot;attachments/8IEUGXVH.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;dfi.call：为捕获输出参数传输的价值流，DFI将&lt;code&gt;llvm.call&lt;/code&gt;替换为&lt;code&gt;dfi.call&lt;/code&gt;&lt;img src=&quot;attachments/8DA727AH.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;8DA727AH&amp;quot; width=&amp;quot;504&amp;quot; height=&amp;quot;148&amp;quot; src=&amp;quot;attachments/8DA727AH.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;attachments/ABUX5456.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;ABUX5456&amp;quot; width=&amp;quot;540&amp;quot; height=&amp;quot;193&amp;quot; src=&amp;quot;attachments/ABUX5456.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;程序内（运行过程内）分析：&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;程序内（运行过程内）分析：&lt;/h3&gt;&lt;p&gt;价值流分析可以归结为一个图可达性问题，其中每个顶点都是程序点上的数据流事实，通过判断两个顶点的可达性来解决价值流分析问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：对于一个给定的价值流分析问题，如果程序中的每一个相关操作都被注释为DFT区间，那么可以通过比较任意两个操作在几乎恒定时间内的区间来判断它们之间的可达性。&lt;img src=&quot;attachments/WYCD2LKH.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;WYCD2LKH&amp;quot; width=&amp;quot;508&amp;quot; height=&amp;quot;220&amp;quot; src=&amp;quot;attachments/WYCD2LKH.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;br&gt;为了演示这个概念，图3给出了一个MLIR函数，其中的值用DFT区间进行了标注。例如，值% p和% 1的区间分别为⟨0，5和⟨1，4。这些区间标注在由SSA定义-引用图衍生的生成树上，由从单个SSA值定义到其用途的边组成。假设对图3进行污点分析，% p为污点值。为了判断返回值% 3是否被污染，只需检查其区间⟨2，3 “是否被% p⟨0，5 “所包含。在这种情况下，由于⟨0，5⋅⊇⟨2，3⋅根据我们在2.3节的定义，返回值是污点。事实上，% 1和% 3都是污点，因为它们的区间都在⟨0，5 “的子树内。另一方面，间隔为⟨7，8的% 0不被污染，因为它位于以⟨6，9为根的不同DFT子树中。”&lt;br&gt;为了计算图3所示的树和相关区间，客户端分析自定义了2.3节中介绍的遍历机制。首先，对于每个函数，客户端分析选择一组根顶点开始遍历。注意，每个函数中的遍历时间戳总是从零开始。其次，对于函数中的每个顶点，通过客户端分析提供一个局部转移函数来指示离开的顶点进行下一次访问。在图3污点分析的背景下，客户端分析选择% a和% p作为遍历根。对于局部传递函数，每类运算的规则如图4所示。以dfi . store规则为例，其中仅当存储值% v被污染时，结果指针% q才被污染。它有效地停止了从% p到% q的DFT遍历，但允许从% v到% q的路径。” &amp;lt;span class=&amp;quot;citation&amp;quot; data-citation=&amp;quot;%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F8438660%2Fitems%2FMZGEWCFE%22%5D%2C%22locator%22%3A%225%22%7D%5D%2C%22properties%22%3A%7B%7D%7D&amp;quot; ztype=&amp;quot;zcitation&amp;quot;&amp;gt;(&amp;lt;span class=&amp;quot;citation-item&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;zotero://select/library/items/MZGEWCFE&amp;quot;&amp;gt;Hsu 等, 2022, p. 5&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;)&amp;lt;/span&amp;gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-def-use-&quot;&gt;&lt;a name=&quot;DEF-USE的非树边&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;DEF-USE的非树边&lt;/h4&gt;&lt;p&gt;非树边的存在抑制了图的可达性在一般SSA的DEF-USE图上的应用，因此，减少非树边是一件很必要的事情。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/IN4VK3R6.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;IN4VK3R6&amp;quot; width=&amp;quot;473&amp;quot; height=&amp;quot;97&amp;quot; src=&amp;quot;attachments/IN4VK3R6.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/IS7HBY7K.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;IS7HBY7K&amp;quot; width=&amp;quot;546&amp;quot; height=&amp;quot;250&amp;quot; src=&amp;quot;attachments/IS7HBY7K.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;h5 id=&quot;h5--&quot;&gt;&lt;a name=&quot;采用反转图：可以有效避免多参数情况下的函数产生的非树边问题。&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;采用反转图：可以有效避免多参数情况下的函数产生的非树边问题。&lt;/h5&gt;&lt;h5 id=&quot;h5--dft-&quot;&gt;&lt;a name=&quot;增广DFT区间图的可达性：在遇到非树边时复制区间，以此可以使用两个区间之间相似的包含关系确定它们的可达性&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;增广DFT区间图的可达性：在遇到非树边时复制区间，以此可以使用两个区间之间相似的包含关系确定它们的可达性&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;区间集&lt;code&gt;Π&lt;/code&gt;:&lt;img src=&quot;attachments/DN6TB9CC.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;DN6TB9CC&amp;quot; width=&amp;quot;267&amp;quot; height=&amp;quot;37&amp;quot; src=&amp;quot;attachments/DN6TB9CC.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;br&gt;其中每个元素之间至少有一个时间戳，满足：&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;区间包含关系，若区间中任意子区间（可以是一个元素）对另一区间存在包含关系，则该区间集包含另一区间：&lt;img src=&quot;attachments/PHTFYY8H.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;PHTFYY8H&amp;quot; width=&amp;quot;431&amp;quot; height=&amp;quot;30&amp;quot; src=&amp;quot;attachments/PHTFYY8H.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;区间合并：两个区间可以通过&lt;code&gt;∪&lt;/code&gt;操作合并。在可达性算法中，每个DEF-USE图的顶点v和一个区间集相关联。vi可以达到vj需满足两个区间集存在包含关系，即：&lt;img src=&quot;attachments/F7IZYE9D.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;F7IZYE9D&amp;quot; width=&amp;quot;425&amp;quot; height=&amp;quot;35&amp;quot; src=&amp;quot;attachments/F7IZYE9D.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;例子&lt;img src=&quot;attachments/BGJDD8RP.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;BGJDD8RP&amp;quot; width=&amp;quot;599&amp;quot; height=&amp;quot;231&amp;quot; src=&amp;quot;attachments/BGJDD8RP.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;h5 id=&quot;h5--lt-span-style-quot-background-color-ff666680-quot-gt-lt-span-gt-&quot;&gt;&lt;a name=&quot;交集运算符&amp;lt;span style=&amp;quot;background-color: #ff666680&amp;quot;&amp;gt;（成立前提？）&amp;lt;/span&amp;gt;&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;交集运算符&amp;lt;span style=&amp;quot;background-color: #ff666680&amp;quot;&amp;gt;（成立前提？）&amp;lt;/span&amp;gt;&lt;/h5&gt;&lt;p&gt;交集运算符指定价值流如何从不同的程序路径进行组合，例如在控制流合并点。在我们的算法中，我们使用区间集合merge∪作为我们的相遇算子。根据我们之前对∪的定义，合并后的区间集总是对传入的区间集的一个安全近似，从而保证了可靠性。” &amp;lt;span class=&amp;quot;citation&amp;quot; data-citation=&amp;quot;%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F8438660%2Fitems%2FMZGEWCFE%22%5D%2C%22locator%22%3A%226%22%7D%5D%2C%22properties%22%3A%7B%7D%7D&amp;quot; ztype=&amp;quot;zcitation&amp;quot;&amp;gt;(&amp;lt;span class=&amp;quot;citation-item&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;zotero://select/library/items/MZGEWCFE&amp;quot;&amp;gt;Hsu 等, 2022, p. 6&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;)&amp;lt;/span&amp;gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u7A0Bu5E8Fu95F4u8FC7u7A0Bu5206u6790&quot;&gt;&lt;a name=&quot;程序间过程分析&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;程序间过程分析&lt;/h3&gt;&lt;p&gt;通过构建一个&lt;strong&gt;函数价值流摘要&lt;/strong&gt;来总结每个函数的价值流。这个价值流摘要被传递到所有它的调用点。由于新引入的被调用方会改变调用方函数内部的价值流，因此该过程将重复执行，直到达到一个固定点。&lt;/p&gt;
&lt;p&gt;函数价值流摘要由&lt;strong&gt;函数参数&lt;/strong&gt;和&lt;strong&gt;输出结果&lt;/strong&gt;之间的一组&lt;strong&gt;可达关系&lt;/strong&gt;组成。摘要描述了参数和结果之间的映射，该映射通过参数和结果索引来表示。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;结果索引等于dfi.call操作的结果列表中对应的索引。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;调用时，原始返回值（若有的话）的索引为0，后面跟着指针参数类型的结果&lt;/p&gt;
&lt;p&gt;我们记I ( p )为参数p的参数指标。此外，O ( p )被定义为p的结果指标，如果p是PT&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;的一部分，PT&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;是f包含所有指针参数的函数参数的子集。函数f的价值流汇总记为Sf = S&amp;lt;sup&amp;gt;R&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;∪S&amp;lt;sup&amp;gt;P&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;。集合S&amp;lt;sup&amp;gt;R&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;和S&amp;lt;sup&amp;gt;P&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;分别表示从函数参数到返回值和输出参数的映射。Rf和Pf是f返回值和参数的集合，S&amp;lt;sup&amp;gt;R&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;被定义为：&lt;img src=&quot;attachments/WZPE9JK6.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;WZPE9JK6&amp;quot; width=&amp;quot;405&amp;quot; height=&amp;quot;34&amp;quot; src=&amp;quot;attachments/WZPE9JK6.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;p&gt;SPf捕获应用于函数f中的指针参数的潜在价值流。它包含指针参数和DFI.call上相应输出结果之间的映射由于指针参数的结果再被调用方中难以定位，因此DFI使用了指针参数和反向根之间的可达性作为近似结果处理。对于任意两个指针参数p0和p1，用&lt;img src=&quot;attachments/RI2STCU8.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;RI2STCU8&amp;quot; width=&amp;quot;139&amp;quot; height=&amp;quot;26&amp;quot; src=&amp;quot;attachments/RI2STCU8.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;和&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;对SPf进行初始化。如果p0和p1都可达逆根┏，那么就可以把&lt;img src=&quot;attachments/PYW7ZHT8.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;PYW7ZHT8&amp;quot; width=&amp;quot;140&amp;quot; height=&amp;quot;28&amp;quot; src=&amp;quot;attachments/PYW7ZHT8.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;和&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;这两个可达条件添加到SPf中，令Tf是f的逆根集合，SPf就被定义为：&lt;img src=&quot;attachments/GMLCBQCM.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;GMLCBQCM&amp;quot; width=&amp;quot;531&amp;quot; height=&amp;quot;70&amp;quot; src=&amp;quot;attachments/GMLCBQCM.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;两个例子&lt;img src=&quot;attachments/N4ZBL47X.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;N4ZBL47X&amp;quot; width=&amp;quot;513&amp;quot; height=&amp;quot;175&amp;quot; src=&amp;quot;attachments/N4ZBL47X.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;列表3：由于存在包含关系&lt;img src=&quot;attachments/AV5WB46N.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;AV5WB46N&amp;quot; width=&amp;quot;193&amp;quot; height=&amp;quot;30&amp;quot; src=&amp;quot;attachments/AV5WB46N.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;因此a，c可达r，SRf == Sf，为：&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;列表4：k’和r’分别对应k和r在一个调用点的结果。由于k和r都可达t1，因此SRf：&lt;img src=&quot;attachments/RSWDCJ2B.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;RSWDCJ2B&amp;quot; width=&amp;quot;512&amp;quot; height=&amp;quot;70&amp;quot; src=&amp;quot;attachments/RSWDCJ2B.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4--&quot;&gt;&lt;a name=&quot;价值流摘要值的传播：将被调者函数的价值流摘要传播到调用者，以便将上下文敏感的价值流信息添加到调用者函数&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;价值流摘要值的传播：将被调者函数的价值流摘要传播到调用者，以便将上下文敏感的价值流信息添加到调用者函数&lt;/h4&gt;&lt;p&gt;得到这些摘要值Sf后，需要将Sf传播到所有调用f的节点。在更高层次（？）上，Sf提供了每个调用f节点所缺的本地价值流映射。通过这些信息可以在调用者函数中添加新的价值流以提高精度。传播包括两步：&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;第一步：对于Sf中每个vs -&amp;gt; vd，在每个调用函数中执行另一轮的反向DFT遍历。不过不采用客户端分析的假根，而是采用vs的实际参数作为反向根。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;第二步：使用第一步的结果在每个调用点上以相反的方向传播&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;一个例子：&lt;img src=&quot;attachments/2W8BVJI8.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;2W8BVJI8&amp;quot; width=&amp;quot;517&amp;quot; height=&amp;quot;56&amp;quot; src=&amp;quot;attachments/2W8BVJI8.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一步：从第八行调用f。在这里使用%s0和%b（实际参数的%v %p）作为反向根进行反向DFT遍历&lt;/li&gt;&lt;li&gt;第二步：将第一步得到的%s0和%b的区间集在增广DFT中过渡性地合并到其父节点和祖先节点（如%s3）的区间集合中，直到达到原来的反向根&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;采用的算法是使用一个基于工作表的算法，递归地改变总结传播给其调用者，直到达到一个固定点：&lt;img src=&quot;attachments/9UUVB3YA.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;9UUVB3YA&amp;quot; width=&amp;quot;548&amp;quot; height=&amp;quot;283&amp;quot; src=&amp;quot;attachments/9UUVB3YA.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;br&gt;在算法1中，GetV FSummary ( f )返回函数f的Sf；PropagateSummary( Sf , c)在调用函数c中执行前面介绍的带有被调用者值-流摘要Sf的两阶段传播。 &amp;lt;span class=&amp;quot;citation&amp;quot; data-citation=&amp;quot;%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F8438660%2Fitems%2FMZGEWCFE%22%5D%2C%22locator%22%3A%227%22%7D%5D%2C%22properties%22%3A%7B%7D%7D&amp;quot; ztype=&amp;quot;zcitation&amp;quot;&amp;gt;(&amp;lt;span class=&amp;quot;citation-item&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;zotero://select/library/items/MZGEWCFE&amp;quot;&amp;gt;Hsu 等, 2022, p. 7&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;)&amp;lt;/span&amp;gt;&lt;/p&gt;
&lt;h4 id=&quot;h4--&quot;&gt;&lt;a name=&quot;可达功能的摘要：将传播过程扩展到一个可达函数的摘要。&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;可达功能的摘要：将传播过程扩展到一个可达函数的摘要。&lt;/h4&gt;&lt;p&gt;通过区间集Π vb⊇Π va确定两个值va和vb在同一函数中的可达性，可以计算具有流量和上下文敏感性的程序间的价值流。在这一部分中，将这种能力推广到任意函数中的va和vb。&lt;br&gt;一个可达函数摘要Ψ ( ε )提供了一个从端点ε到可通行端点集合的映射。端点ε&amp;lt;sup&amp;gt;i&amp;lt;/sup&amp;gt;&amp;lt;sub&amp;gt;f&amp;lt;/sub&amp;gt;表示函数f的第i个参数。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;一个例子：&lt;img src=&quot;attachments/MHXE2T5R.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;MHXE2T5R&amp;quot; width=&amp;quot;536&amp;quot; height=&amp;quot;206&amp;quot; src=&amp;quot;attachments/MHXE2T5R.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;ε&lt;/p&gt;
&lt;p&gt;&amp;lt;sup&amp;gt;0&amp;lt;/sup&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;sub&amp;gt;f  &amp;lt;/sub&amp;gt;&lt;/p&gt;
&lt;p&gt;的摘要值为：&lt;img src=&quot;attachments/R59EU2M8.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;R59EU2M8&amp;quot; width=&amp;quot;194&amp;quot; height=&amp;quot;40&amp;quot; src=&amp;quot;attachments/R59EU2M8.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;对于函数所有的所有参数，Ψ被反复传播到它的所有调用者，并与它们的摘要值合并，直到达到一个固定值，即所有可达函数的摘要值都不发生变化为止。&lt;/p&gt;
&lt;p&gt;对于某个可达函数摘要，可以执行一个两阶段的过程来回答不同函数中的va-&amp;gt;vb是否是可达的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;计算集合&lt;img src=&quot;attachments/W8I72BH7.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;W8I72BH7&amp;quot; width=&amp;quot;328&amp;quot; height=&amp;quot;34&amp;quot; src=&amp;quot;attachments/W8I72BH7.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt; 检查对于任意的索引j&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;是否包含函数g的端点ε&lt;/p&gt;
&lt;p&gt;&amp;lt;sup&amp;gt;j&amp;lt;/sup&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;sub&amp;gt;g&amp;lt;/sub&amp;gt;&lt;/p&gt;
&lt;p&gt;。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;只有当前端点ε&lt;/p&gt;
&lt;p&gt;&amp;lt;sup&amp;gt;j&amp;lt;/sup&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;sub&amp;gt;g &amp;lt;/sub&amp;gt;&lt;/p&gt;
&lt;p&gt;可以达到vb时，va才能达到vb，即：&lt;img src=&quot;attachments/V46LADJM.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;V46LADJM&amp;quot; width=&amp;quot;203&amp;quot; height=&amp;quot;33&amp;quot; src=&amp;quot;attachments/V46LADJM.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id=&quot;h2-u8BC4u4F30&quot;&gt;&lt;a name=&quot;评估&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;评估&lt;/h2&gt;&lt;p&gt;回答两个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在大型代码库上的扩展效果如何，如其他的价值流分析工具相比？&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;DFI中回答图的可达性的效率与每个顶点关联的区间集的大小强相关。在所有顶点上间隔集的大小分布如何？&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/5GEX7V4X.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;5GEX7V4X&amp;quot; width=&amp;quot;528&amp;quot; height=&amp;quot;112&amp;quot; src=&amp;quot;attachments/5GEX7V4X.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;img src=&quot;&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;所有实验在10分钟内完成，使用的物理内存不超过4.5 GB。&lt;/p&gt;
</description><pubDate>Fri, 26 May 2023 11:31:38 +0800</pubDate></item><item><title>TRUSTFLOW：降低DFI内存开销的硬件DFI机制</title><link>http://152.136.151.227/?id=16</link><description>&lt;h2 id=&quot;h2-u4E00u53E5u8BDDu6982u8FF0&quot;&gt;&lt;a name=&quot;一句话概述&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;一句话概述&lt;/h2&gt;&lt;p&gt;设计了低开销细粒度的DFI硬件机制，对软件开销影响度为0%&lt;/p&gt;
&lt;h2 id=&quot;h2-u4E3Bu8981u529Fu80FD&quot;&gt;&lt;a name=&quot;主要功能&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;主要功能&lt;/h2&gt;&lt;p&gt;一个旁路的硬件设备，备份内存中的敏感数据，可以跟踪数据流完整性、检测内存漏洞、记录异常，敏感数据被篡改时还原数据。&lt;/p&gt;
&lt;h2 id=&quot;h2-u4E3Bu8981u8D21u732E&quot;&gt;&lt;a name=&quot;主要贡献&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;主要贡献&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;提出TRUSTFLOW：一个具备针对数据细粒度预防、检测和处理基于内存漏洞的新概念&lt;/li&gt;&lt;li&gt;采用RISC-V架构的TRUSTFLOW的硬件实现，使用Chisel中的Rocket Chip generator生成&lt;/li&gt;&lt;li&gt;扩展RISC-V GNU指令：新增了两条保护内存敏感数据的指令&lt;/li&gt;&lt;li&gt;修改了RISC-V GNU工具链，使得3中的两条指令可以应用于编译器&lt;/li&gt;&lt;li&gt;评估：使用生命关键型应用进行评估&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id=&quot;h2-trustflow&quot;&gt;&lt;a name=&quot;TRUSTFLOW&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;TRUSTFLOW&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;前提假设&lt;/strong&gt;：系统上运行的软件包括缓冲区溢出、off-by-one或格式化字符串等漏洞，且软件皆以经过静态认证，且不包含任何恶意软件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;rowhammer和侧信道攻击不计入本实验讨论范围&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心理念&lt;/strong&gt;：检测攻击的过程应与保护关键系统的敏感数据一样重要&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;详细设计&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;添加一块可信内存，TRUSTFLOW提供自定义加载和自定义存储。该内存备份普通内存中的敏感信息（如令牌、返回地址、指针、迭代数据等），该内存中不仅保存敏感信息的地址，还保存敏感信息的值。当普通内存中的敏感数据安全更新时，可信内存也一同更新（保护敏感数据）&lt;img src=&quot;attachments/CZPVLBZP.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;CZPVLBZP&amp;quot; width=&amp;quot;595&amp;quot; height=&amp;quot;337&amp;quot; src=&amp;quot;attachments/CZPVLBZP.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;使用转译后备缓冲区（TLB）作为信任内存，该内存通过单个时钟实现查找表提供高速搜索功能，该内存速度与L1缓存一致，因此不会产生多余开销&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;为优化空间使用，TRUSTFLOW会删除属于堆栈中已释放地址的受信任内存条目&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;新增指令：sws和lws，这两个指令继承经典sw和lw的功能，并可以与可信的转译后备缓冲区TLB（可信内存）交互&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sws rs, imm(rd)：存储一个字并在可信内存中复制一份（特权级指令）&lt;/li&gt;&lt;li&gt;lws rd, imm(rs)：加载一个字并使用可信内存中的数据检查其完整性（特权级指令）&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;指令使用时，在存储阶段，管道检测到自定义指令信号(“mem_reg_inst信号“)。然后，增加的逻辑会检索管道中用于处理敏感字(“io_req_bits_addr“,“io_dmem_resp_bit_data“)和敏感地址(“memAddr“)的信号，这些信号需要存储、检测到可信内存或从可信内存中取出。最后，在使用可信内存执行决策性操作之前，管道的最后会检查这些自定义指令的有效性来确保不会将不稳定的数据放入可信内存中。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/5RE9X8TZ.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;5RE9X8TZ&amp;quot; width=&amp;quot;1210&amp;quot; height=&amp;quot;536&amp;quot; src=&amp;quot;attachments/5RE9X8TZ.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;内存访问阶段&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用“mem_reg_inst”信号检测自定义指令&lt;/li&gt;&lt;li&gt;从ALU输出中检索加载/存储字的地址(“io_req_bits_addr信号“)&lt;/li&gt;&lt;li&gt;对于sws指令，要存储在内存中的字在”mem_reg_rs2”信号中处理&lt;/li&gt;&lt;li&gt;扩展等待回写阶段以确认指令的有效性&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;回写阶段&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在阶段1中使用lws指令内存加载的字由”io_dmem_resp_bit_data”信号中的&lt;strong&gt;影子逻辑&lt;/strong&gt;收集&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;如果自定义指令在这个阶段有效，那么相应的操作将由&lt;strong&gt;影子逻辑&lt;/strong&gt;继续执行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sws：在”mem_reg_rs2”中包含的字与”io_req_bits_addr”中包含的地址将被发送到信任内存(TLB)中&lt;/li&gt;&lt;li&gt;lws：将”io_dmem_resp_bit_data”信号中包含的字与影子内存中的”io_req_bits_addr”地址处的字进行比较，若出现差异，则引发数据流异常&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;可信TLB的输出接口直接连接到核心异常和处理器上的寄存器堆。当发生异常时，操作系统可以记录并报告异常；同时，损坏的数据在写入寄存器堆之前被可信TLB中的健康数据替换。如果管道中内存访问阶段或执行阶段存在危害，则健康数据将从回写阶段转发到内存访问阶段或执行阶段。&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id=&quot;h2-u7F16u8BD1u5668u652Fu6301&quot;&gt;&lt;a name=&quot;编译器支持&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;编译器支持&lt;/h2&gt;&lt;p&gt;自定义指令支持被移植到RISC-V GNU工具链，添加的指令没有用过多代码。预定义部分添加代码如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/79C59TLH.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;79C59TLH&amp;quot; width=&amp;quot;460&amp;quot; height=&amp;quot;183&amp;quot; src=&amp;quot;attachments/79C59TLH.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“MASK“值定义了指令中固定的位&lt;/li&gt;&lt;li&gt;“MATCH“用于定义由”MASK”设置的固定位的位值。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;可以看到，”MASK”和原先的值是一样的，它们通过不同的”MATCH”进行区分。&lt;/p&gt;
&lt;h2 id=&quot;h2--trustflow-&quot;&gt;&lt;a name=&quot;基于TRUSTFLOW的安全策略&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;基于TRUSTFLOW的安全策略&lt;/h2&gt;&lt;p&gt;TRUSTFLOW的策略是灵活的，可以实现&lt;strong&gt;影子堆栈&lt;/strong&gt;和&lt;strong&gt;指针完整性&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u5F71u5B50u5806u6808&quot;&gt;&lt;a name=&quot;影子堆栈&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;影子堆栈&lt;/h3&gt;&lt;p&gt;函数调用时，函数地址放置在调用堆栈和影子对战中；函数返回时，返回地址同时从调用堆栈和影子堆栈弹出，若两个值不同，则检测到内存冲突。下图右侧为使用了TRUSTFLOW实现的影子堆栈：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/C2VAFQPB.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;C2VAFQPB&amp;quot; width=&amp;quot;378&amp;quot; height=&amp;quot;155&amp;quot; src=&amp;quot;attachments/C2VAFQPB.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;p&gt;TRUSTFLOW可以解决影子堆栈经典[setjmp/longjmp](&lt;a href=&quot;https://zhuanlan.zhihu.com/p/464553050&quot;&gt;https://zhuanlan.zhihu.com/p/464553050&lt;/a&gt;)失败问题。当长跳转时，影子堆栈中的返回地址与调用堆栈的返回地址大概率不匹配；而TRUSTFLOW的设计中，只在重新访问敏感数据时检查数据完整性，而不会出现在返回过程中。&lt;/p&gt;
&lt;h3 id=&quot;h3-u6307u9488u5B8Cu6574u6027&quot;&gt;&lt;a name=&quot;指针完整性&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;指针完整性&lt;/h3&gt;&lt;p&gt;通过篡改函数指针（间接调用）达到破坏控制流是常见做法，TRUSTFLOW可以通过指令级操作完成对函数指针的保护。&lt;/p&gt;
&lt;p&gt;其弊端是需要开发者选择敏感指针进行保护，对开发人员专业素养要求很高。&lt;/p&gt;
&lt;h3 id=&quot;h3-u5FAAu73AFu76D1u6D4Bu548Cu901Au7528u6570u636E&quot;&gt;&lt;a name=&quot;循环监测和通用数据&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;循环监测和通用数据&lt;/h3&gt;&lt;p&gt;部分攻击针对循环迭代数据，使程序失常。通过控制循环，攻击者可能会溢出缓冲区或从内存中泄露一些秘密字节。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/56E6CYA4.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;56E6CYA4&amp;quot; width=&amp;quot;411&amp;quot; height=&amp;quot;208&amp;quot; src=&amp;quot;attachments/56E6CYA4.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;p&gt;上图右边使用定制化指令进行数据保护（使用影子内存），可以降低循环中非控制数据攻击的有效性。&lt;/p&gt;
&lt;h2 id=&quot;h2-u8BC4u4F30&quot;&gt;&lt;a name=&quot;评估&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;评估&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;影子逻辑所用范围&lt;/li&gt;&lt;li&gt;使用[”very secure pump model”](&lt;a href=&quot;https://github.com/r3glisss/SecPump&quot;&gt;https://github.com/r3glisss/SecPump&lt;/a&gt;)等生命关键软件挑战TRUSTFLOW&lt;/li&gt;&lt;li&gt;软件层面，评估用于2类应用程序的信任内存的百分比&lt;/li&gt;&lt;/ol&gt;
&lt;h3 id=&quot;h3-vspm-&quot;&gt;&lt;a name=&quot;VSPM实验结果&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;VSPM实验结果&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;测试环境&lt;/strong&gt;：存在内存损坏漏洞的VSPM，允许攻击者控制执行流，能够改变关键设备的行为并注射致命剂量给患者。&lt;/p&gt;
&lt;p&gt;应用有：4205条指令，89个函数、1000+行C代码&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结果&lt;/strong&gt;：程序正常运行，保护的敏感数据约为0.25KB&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;attachments/FISIYRF3.png&quot; alt=&quot;\&amp;lt;img alt=&amp;quot;&amp;quot; data-attachment-key=&amp;quot;FISIYRF3&amp;quot; width=&amp;quot;434&amp;quot; height=&amp;quot;268&amp;quot; src=&amp;quot;attachments/FISIYRF3.png&amp;quot; ztype=&amp;quot;zimage&amp;quot;&amp;gt;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u4E0Du8DB3&quot;&gt;&lt;a name=&quot;不足&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;不足&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;空间换时间：所需额外的TLB空间不小&lt;/li&gt;&lt;li&gt;没有良好分析工具：该方法当下只能手动选取敏感节点替换”lws”和”sws”&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Referred in &lt;a href=&quot;zotero://note/u/A25ANMK6/?ignore=1&amp;line=-1&quot;&gt;研究生毕设&lt;/a&gt;&lt;/p&gt;
</description><pubDate>Fri, 26 May 2023 11:30:33 +0800</pubDate></item><item><title>Linux通用配置相关问题（持续更新）</title><link>http://152.136.151.227/?id=15</link><description>&lt;h2 id=&quot;h2-apt-dnf-apt-&quot;&gt;&lt;a name=&quot;apt/dnf/apt自动安装路径&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;apt/dnf/apt自动安装路径&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/tpm2-software/tpm2-tools/issues/1302#issuecomment-1442180486&quot;&gt;参考这个回答&lt;/a&gt;一般而言，Linux不同发行版采用pkg-config功能会自设一个安装路径，使用&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;pkg-config --variable=pc_path pkg-config&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以查看默认的安装路径，&lt;strong&gt;当源码安装依赖后，相关程序无法找到依赖时需要注意路径&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u8E29u5751u6848u4F8B&quot;&gt;&lt;a name=&quot;踩坑案例&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;踩坑案例&lt;/h3&gt;&lt;p&gt;某次编译报错：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230401232734.png&quot; alt=&quot;20230401232734&quot;&gt;&lt;/p&gt;
&lt;p&gt;其中，tpm2-tss v2.3.2版本的软件是dnf自动安装的，软件需求v2.3.3版本以上，而本机已经安装2.3.3版本，仍然报错，查看pkg-config默认路径&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230401232922.png&quot; alt=&quot;20230401232922&quot;&gt;&lt;/p&gt;
&lt;p&gt;而2.3.3版本安装在&lt;code&gt;/usr/local/lib/pkgconfig&lt;/code&gt;中，因此无法索引到2.3.3版。此时我的解决方案是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;删除老版本&lt;code&gt;dnf remove tpm2-tss-devel&lt;/code&gt;&lt;/li&gt;&lt;li&gt;复制新版的.pc文件&lt;code&gt;cp -a /usr/local/pkgconfig/*.pc /usr/lib64/pkgconfig/&lt;/code&gt;&lt;/li&gt;&lt;li&gt;再次编译，通过&lt;/li&gt;&lt;/ol&gt;
</description><pubDate>Fri, 26 May 2023 11:26:08 +0800</pubDate></item><item><title>TOOLS</title><link>http://152.136.151.227/?id=14</link><description>&lt;p&gt;&lt;em&gt;内核版本：5.19.0&lt;/em&gt;&lt;br&gt;说明：本博客为学习笔记，仅做记录用。&lt;/p&gt;
&lt;h2 id=&quot;h2-bpf_tracing-h&quot;&gt;&lt;a name=&quot;bpf_tracing.h&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;bpf_tracing.h&lt;/h2&gt;&lt;h3 id=&quot;h3-bpf_prog&quot;&gt;&lt;a name=&quot;BPF_PROG&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;BPF_PROG&lt;/h3&gt;&lt;p&gt;bpf中PROG实现，以宏定义形式给出&lt;br&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v5.19/source/tools/lib/bpf/bpf_tracing.h#L425&quot;&gt;源码：tools/lib/bpf/bpf_tracing.h#L425&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;#define BPF_PROG(name, args...)                            \
name(unsigned long long *ctx);                            \
static __attribute__((always_inline)) typeof(name(0))                \ // 返回值
____##name(unsigned long long *ctx, ##args);                    \  // 实际函数名
typeof(name(0)) name(unsigned long long *ctx)                    \
{                                        \
    _Pragma(&amp;quot;GCC diagnostic push&amp;quot;)                        \
    _Pragma(&amp;quot;GCC diagnostic ignored \&amp;quot;-Wint-conversion\&amp;quot;&amp;quot;)            \
    return ____##name(___bpf_ctx_cast(args));                \   // 真正执行内容
    _Pragma(&amp;quot;GCC diagnostic pop&amp;quot;)                        \
}                                        \
static __attribute__((always_inline)) typeof(name(0))                \
____##name(unsigned long long *ctx, ##args)&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Fri, 26 May 2023 11:23:30 +0800</pubDate></item><item><title>PERF &amp;amp; RING BUFFER</title><link>http://152.136.151.227/?id=13</link><description>&lt;h2 id=&quot;h2-u603Bu8FF0&quot;&gt;&lt;a name=&quot;总述&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;总述&lt;/h2&gt;&lt;p&gt;BPF中，&lt;strong&gt;内核向用户空间&lt;/strong&gt;发送数据使用的缓冲区称为&lt;strong&gt;PERF&lt;/strong&gt;缓冲区；在Linux 5.8版本之后，可以使用环形缓冲区&lt;strong&gt;RING BUFFER（RB）&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-ring-buffer-&quot;&gt;&lt;a name=&quot;RING BUFFER优势&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;RING BUFFER优势&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;降低内存开销：PERF为&lt;strong&gt;每个CPU分配缓存&lt;/strong&gt;；RB为&lt;strong&gt;所有CPU分配一个共享的大缓冲区&lt;/strong&gt;&lt;ol&gt;
&lt;li&gt;“大缓冲区”一位置更好容忍数据毛刺&lt;/li&gt;&lt;li&gt;内存使用效率更高&lt;/li&gt;&lt;li&gt;内存拓展性更好，如CPU数量增加时，PERF的buffer跟着翻倍，而RB可能不需要新增那么多内存&lt;/li&gt;&lt;/ol&gt;
&lt;/li&gt;&lt;li&gt;保证事件顺序：由于per-CPU特性， 如果事件发生间隔非常短且分散在不同CPU中，事件的发送顺序就可能乱掉；RB由于共享同一个缓冲区，就不会有上述问题&lt;/li&gt;&lt;li&gt;减少数据复制：PERF必须先初始化一份事件数据，然后复制到perfbuf，之后发送到用户口空间，因此，数据会被复制两次；RB会首先为数据预留空间，预留成功后可以直接把发送的数据放到RB中，无需像PERF一样多一次将数据复制到局部变量中&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id=&quot;h2-perf-rf-&quot;&gt;&lt;a name=&quot;PERF和RF主要结构对比&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;PERF和RF主要结构对比&lt;/h2&gt;&lt;p&gt;PERF：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;struct perf_buffer {
    perf_buffer_event_fn event_cb;
    perf_buffer_sample_fn sample_cb;
    perf_buffer_lost_fn lost_cb;
    void *ctx; /* passed into callbacks */

    size_t page_size;
    size_t mmap_size;
    struct perf_cpu_buf **cpu_bufs;
    struct epoll_event *events;
    int cpu_cnt; /* number of allocated CPU buffers */
    int epoll_fd; /* perf event FD */
    int map_fd; /* BPF_MAP_TYPE_PERF_EVENT_ARRAY BPF map FD */
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;RB:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;struct ring_buffer {
    struct epoll_event *events;
    struct ring *rings;
    size_t page_size;
    int epoll_fd;
    int ring_cnt;
};&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2-u4F8Bu7A0B&quot;&gt;&lt;a name=&quot;例程&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;例程&lt;/h2&gt;&lt;p&gt;见&lt;a href=&quot;https://arthurchiao.art/blog/bpf-ringbuf-zh/#31-perfbuf-%E7%A4%BA%E4%BE%8B&quot;&gt;该篇博客&lt;/a&gt;第三部分&lt;/p&gt;
</description><pubDate>Fri, 26 May 2023 10:35:11 +0800</pubDate></item><item><title>eBPF概述</title><link>http://152.136.151.227/?id=12</link><description>&lt;h2 id=&quot;h2-u8D77u6E90&quot;&gt;&lt;a name=&quot;起源&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;起源&lt;/h2&gt;&lt;p&gt;1992年论文，其提出了一个&lt;strong&gt;由内核直接过滤网络包，减少用户态的无效克隆&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411225136.png&quot; alt=&quot;20230411225136&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2--bpf-jit&quot;&gt;&lt;a name=&quot;伪机器码、BPF指令集、JIT&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;伪机器码、BPF指令集、JIT&lt;/h2&gt;&lt;h3 id=&quot;h3-u4F2Au673Au5668u7801&quot;&gt;&lt;a name=&quot;伪机器码&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;伪机器码&lt;/h3&gt;&lt;p&gt;不能在物理机上直接运行，需要在虚拟机上执行&lt;/p&gt;
&lt;h3 id=&quot;h3-bpf-&quot;&gt;&lt;a name=&quot;BPF指令集&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;BPF指令集&lt;/h3&gt;&lt;p&gt;是伪机器码，在初期由于BPF功能较少，只用在网络数据包过滤，因此早期的BPF指令集只需要几个库（如tcpdump的实现基于libcap库）就可以将一般的表达式生成BPF指令集；&lt;/p&gt;
&lt;p&gt;但随着BPF的发展，指令集的复杂、支持的BPF程序类型增多，就需要编译器了&lt;/p&gt;
&lt;h3 id=&quot;h3-jit&quot;&gt;&lt;a name=&quot;JIT&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;JIT&lt;/h3&gt;&lt;p&gt;&lt;code&gt;just in time&lt;/code&gt;的缩写，用于将BPF指令直接编译成机器码，大大提高了执行效率&lt;/p&gt;
&lt;h2 id=&quot;h2-ebpf-&quot;&gt;&lt;a name=&quot;eBPF介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;eBPF介绍&lt;/h2&gt;&lt;p&gt;eBPF是extend BPF的简称，也就是扩展的BPF。因此早期的BPF称为cBPF&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411230949.png&quot; alt=&quot;20230411230949&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u4E8Cu8005u5BF9u6BD4&quot;&gt;&lt;a name=&quot;二者对比&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;二者对比&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411231029.png&quot; alt=&quot;20230411231029&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-ebpf-map-&quot;&gt;&lt;a name=&quot;eBPF类型和Map机制&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;eBPF类型和Map机制&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411231128.png&quot; alt=&quot;20230411231128&quot;&gt;&lt;/p&gt;
&lt;p&gt;Map机制中，内核和用户共享一块内存，一般由内核存，用户取&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411231202.png&quot; alt=&quot;20230411231202&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-u6240u7528u8BEDu8A00&quot;&gt;&lt;a name=&quot;所用语言&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;所用语言&lt;/h3&gt;&lt;p&gt;cBPF是直接写指令，后发展为C语言，通过clang/llvm进行编译为字节码，注入还是要手动&lt;/p&gt;
&lt;p&gt;因此出现了python的bcc库和更新的libbpf，其完成了&lt;code&gt;编译、解析ELF、加载BPF代码以及创建map&lt;/code&gt;，用户只需要设计bpf代码&lt;/p&gt;
&lt;p&gt;工作原理如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411231437.png&quot; alt=&quot;20230411231437&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-bpf-&quot;&gt;&lt;a name=&quot;BPF作用&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;BPF作用&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230411231607.png&quot; alt=&quot;20230411231607&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-libbpf-hook-&quot;&gt;&lt;a name=&quot;libbpf支持的hook点（节选）&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;libbpf支持的hook点（节选）&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230426180222.png&quot; alt=&quot;20230426180222&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20230426181704.png&quot; alt=&quot;20230426181704&quot;&gt;&lt;/p&gt;
</description><pubDate>Fri, 26 May 2023 10:26:33 +0800</pubDate></item><item><title>PVE为虚拟机添加vmdk硬盘</title><link>http://152.136.151.227/?id=11</link><description>&lt;h1 id=&quot;h1-pve-vmdk-&quot;&gt;&lt;a name=&quot;PVE为虚拟机添加vmdk硬盘&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;PVE为虚拟机添加vmdk硬盘&lt;/h1&gt;&lt;p&gt;&lt;em&gt;pve版本：7.2.1&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u521Bu5EFAu865Au62DFu673A&quot;&gt;&lt;a name=&quot;创建虚拟机&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;创建虚拟机&lt;/h2&gt;&lt;p&gt;不添加磁盘，使用&lt;code&gt;Seabios&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u5BFCu5165u78C1u76D8u6587u4EF6&quot;&gt;&lt;a name=&quot;导入磁盘文件&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;导入磁盘文件&lt;/h2&gt;&lt;p&gt;在上传vmdk之后，键入如下指令导入磁盘到镜像中&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;qm importdisk [vmID] [vmdk] local-lvm --format qcow2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出现如下图所示过程，并在dashboard中对应虚拟机出现磁盘即为成功&lt;br&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141053.png&quot; alt=&quot;20221103141053&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141127.png&quot; alt=&quot;20221103141127&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u6302u8F7Du78C1u76D8&quot;&gt;&lt;a name=&quot;挂载磁盘&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;挂载磁盘&lt;/h2&gt;&lt;p&gt;双击&lt;code&gt;未使用的磁盘&lt;/code&gt;，修改其为总线设备&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141355.png&quot; alt=&quot;20221103141355&quot;&gt;&lt;/p&gt;
&lt;p&gt;完成后点击&lt;code&gt;添加&lt;/code&gt;，完成磁盘挂载。&lt;/p&gt;
&lt;h2 id=&quot;h2-u4FEEu6539u542Fu52A8u987Au5E8F&quot;&gt;&lt;a name=&quot;修改启动顺序&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;修改启动顺序&lt;/h2&gt;&lt;p&gt;进入&lt;code&gt;选项&lt;/code&gt;栏，双击修改引导顺序&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141517.png&quot; alt=&quot;20221103141517&quot;&gt;&lt;/p&gt;
&lt;p&gt;首先启用ide0&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141654.png&quot; alt=&quot;20221103141654&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后拖拽&lt;code&gt;ide0&lt;/code&gt;设备到第一引导设备&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141748.png&quot; alt=&quot;20221103141748&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2-u542Fu52A8u6D4Bu8BD5&quot;&gt;&lt;a name=&quot;启动测试&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;启动测试&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://typora-picture-store.oss-cn-beijing.aliyuncs.com/img/20221103141906.png&quot; alt=&quot;20221103141906&quot;&gt;&lt;/p&gt;
&lt;p&gt;完成&lt;/p&gt;
</description><pubDate>Mon, 07 Nov 2022 17:24:29 +0800</pubDate></item></channel></rss>