Linux 安全 - Capabilities机制

文章目录

  • 前言
  • 一、简介
  • 二、Capabilities list
    • 2.1 POSIX-draft defined capabilities
    • 2.2 Linux-specific capabilities
  • 三、 Past and current implementation
  • 四、Thread capability sets
  • 五、File capabilities
  • 六、Transformation of capabilities during execve()
  • 七、Capabilities and execution of programs by root
  • 八、Capability bounding set
  • 九、Effect of user ID changes on capabilities
  • 十、 Programmatically adjusting capability sets
  • 参考资料

前言

在这两篇文章中介绍了 Linux 安全机制 Credentials :Linux 安全 - Credentials,以及 Linux 安全 - SUID机制。

接下来我们详细介绍Capabilities,在介绍Capabilities之前先简单的和SUID机制对比一下:

在Linux中,除了SUID权限之外,还有一种更为细粒度的权限控制机制,称为Capabilities(能力)。Capabilities提供了对特定操作或系统资源的更细粒度的权限控制,以允许用户或进程执行特定的特权操作,而无需完全提升到超级用户(root)权限。

SUID权限和Capabilities的主要区别在于权限的粒度和授予权限的方式:
(1)SUID权限:SUID权限是应用于可执行文件的一种特殊权限位,允许普通用户在执行该文件时以文件所有者的权限运行。这意味着用户可以临时获得与文件所有者相同的权限级别,从而执行一些需要特权的操作。然而,SUID权限的授予是基于文件的整体权限,而不是基于特定操作。

(2)Capabilities:Capabilities是一种更细粒度的权限控制机制,它允许进程在不完全提升到超级用户权限的情况下执行特定的特权操作。相比于SUID权限,Capabilities允许对特定的系统功能或资源进行更细粒度的控制,而不必完全获得文件所有者的权限。例如,某些操作可能需要访问网络套接字、执行系统管理任务、挂载文件系统等。使用Capabilities,可以授予进程仅限于执行这些特定操作所需的权限,而不必提升到完全的超级用户权限。这使得权限控制更加细致,并可以减少潜在的安全风险。

SUID权限是一个文件级别的权限机制,允许以文件所有者的权限执行文件。而Capabilities是一种更细粒度的权限机制,允许进程在不完全提升到超级用户权限的情况下执行特定的特权操作。两者都提供了在普通用户环境下执行特权操作的机制,但Capabilities提供了更灵活和细粒度的权限控制。

一、简介

NAMEcapabilities - overview of Linux capabilities

为了进行权限检查,传统的UNIX实现将进程分为两类:特权进程(有效用户ID为0,也称为超级用户或root)和非特权进程(有效用户ID非零)。特权进程可以绕过所有内核权限检查,而非特权进程则需根据进程的凭据(通常是有效用户ID、有效组ID和附加组列表)进行完整的权限检查。

从内核2.2版本开始,Linux将传统上与超级用户相关联的特权分为不同的单元,称为能力(capabilities),这些能力可以独立地启用和禁用。能力是每个线程的属性。

在Linux中,能力提供了一种细粒度的权限控制机制。传统上,超级用户拥有完整的系统权限,但在使用能力的情况下,特权可以分解为多个单独的能力,每个能力都代表一项特定的权限。通过启用或禁用不同的能力,可以以更细粒度的方式控制进程的特权。这样可以提高系统的安全性,使特权进程只具有执行特定任务所需的必要权限,而非特权进程则受到更严格的权限检查。

需要注意的是,能力是线程级别的属性,因此不同线程可以具有不同的能力配置。它们可以通过使用prctl系统调用来设置和修改。能力的使用在Linux系统中提供了一种更灵活和精细的权限管理机制。

通俗来一点说就是:传统UNIX系统中控制进程的权限,要么是高权限的 root 用户,要么是一般权限的普通用户,这时候的问题是,root 用户权限太大,而普通用户权限太小。有时候一个普通用户想做一点高权限的事情,必须给他整个 root 的权限。这个太不安全了。

对于普通用户运行的进程,当有某个权限(权限请参考:Capabilities list)的时候,就能做这些操作;没有的时候,就不能做,这样粒度要小很多。

二、Capabilities list

以下列表显示了在Linux上实现的 capabilities ,以及每个 capabilities 允许的操作或行为:

2.1 POSIX-draft defined capabilities

CAP_CHOWN:允许覆盖更改文件所有者和组所有者的限制。
CAP_DAC_OVERRIDE:允许覆盖所有DAC(自主访问控制)访问限制,包括ACL(访问控制列表)的执行访问控制。
CAP_DAC_READ_SEARCH:允许覆盖对文件和目录的读取和搜索操作的所有限制。
CAP_FOWNER:允许覆盖对文件所有者ID必须等于用户ID的操作的限制。
CAP_FSETID:允许覆盖对文件设置S_ISUID和S_ISGID位的限制。
CAP_KILL:允许覆盖发送信号的进程的实际或有效用户ID必须与接收信号的进程的实际或有效用户ID相匹配的限制。
CAP_SETGID:允许操作组ID设置。
CAP_SETUID:允许操作用户ID设置。

更详细请参考 man Capabilities 和 文件:

linux-5.4.18/include/uapi/linux/capability.h

2.2 Linux-specific capabilities

CAP_SETPCAP:允许修改进程的能力。
CAP_LINUX_IMMUTABLE:允许修改文件属性S_IMMUTABLE和S_APPEND。
CAP_NET_BIND_SERVICE:允许绑定到低于1024的TCP/UDP套接字。
CAP_NET_BROADCAST:允许广播和监听多播。
CAP_NET_ADMIN:允许接口配置、管理IP防火墙和路由表、设置套接字的调试选项等。
CAP_NET_RAW:允许使用RAW和PACKET套接字。
CAP_IPC_LOCK:允许锁定共享内存段和mlock/mlockall调用。
CAP_IPC_OWNER:覆盖IPC所有权检查。
CAP_SYS_MODULE:允许插入和删除内核模块。
CAP_SYS_RAWIO:允许原始I/O访问和向任何设备发送USB消息。
CAP_SYS_CHROOT:允许使用chroot()。
CAP_SYS_PTRACE:允许对任何进程进行ptrace()。
CAP_SYS_PACCT:允许配置进程账户。
CAP_SYS_ADMIN:允许各种管理任务,如挂载/卸载、访问设备特定功能等。
CAP_SYS_BOOT:允许使用reboot()。
CAP_SYS_NICE:允许提高其他进程的优先级和设置优先级。
CAP_SYS_RESOURCE:允许覆盖资源限制和配额限制,修改数据日志模式等。
CAP_SYS_TIME:允许配置系统时钟和设置实时时钟。
CAP_SYS_TTY_CONFIG:允许配置tty设备和vhangup()tty。
CAP_MKNOD:允许特权方面的mknod()。
CAP_LEASE:允许对文件进行租约。
CAP_AUDIT_WRITE:允许通过单播netlink套接字写入审计日志。
CAP_AUDIT_CONTROL:允许通过单播netlink套接字配置审计。
CAP_SETFCAP:允许设置文件能力。
CAP_MAC_OVERRIDE:覆盖MAC(强制访问控制)访问。
CAP_MAC_ADMIN:允许MAC配置或状态更改。
CAP_SYSLOG:允许配置内核的系统日志。
CAP_WAKE_ALARM:允许触发将唤醒系统的事件。
CAP_BLOCK_SUSPEND:允许阻止系统挂起。
CAP_AUDIT_READ:允许通过多播netlink套接字读取审计日志。

更详细请参考 man Capabilities 和 文件:

linux-5.4.18/include/uapi/linux/capability.h

三、 Past and current implementation

完整的能力实现需要满足以下条件:
(1)对于所有特权操作,内核必须检查线程是否在其有效能力集中具有所需的能力。

(2)内核必须提供系统调用,允许更改和检索线程的能力集。

(3)文件系统必须支持将能力附加到可执行文件,以便在执行文件时进程获取这些能力。

四、Thread capability sets

每个线程都有以下 capability sets ,包含零个或多个上述的 capabilities :

struct cred {kernel_cap_t	cap_inheritable; /* caps our children can inherit */kernel_cap_t	cap_permitted;	/* caps we're permitted */kernel_cap_t	cap_effective;	/* caps we can actually use */kernel_cap_t	cap_bset;	/* capability bounding set */kernel_cap_t	cap_ambient;	/* Ambient capability set */
}

(1)Permitted:该权限集合是线程可以使用的权限的上限。它定义了线程能够拥有的最大权限。如果线程从允许的权限集合中删除了某个权限,那么除非它执行一个具有相应文件权限的程序,否则它将无法重新获取该权限。

(2)Inheritable:该权限集合中包含了在执行execve()系统调用时会保留的权限。可继承的权限在执行任何程序时都会被保留,并且如果某个程序的文件可继承权限集合中相应的位被设置了,那么这些权限将被添加到允许的权限集合中。然而,可继承的权限通常在以非root用户身份运行时不会被保留,因此需要以提升的权限运行辅助程序的应用程序应考虑使用环境权限(下面介绍)。

简而言之:cap_inheritable 表示当可执行文件的扩展属性设置了 inheritable 位时,调用 exec 执行该程序会继承调用者的 inheritable 集合,并将其加入到 permitted 集合。但在非 root 用户下执行 exec 时,通常不会保留 inheritable 集合,但是往往又是非 root 用户,才想保留权限,所以Inheritable没有什么作用,因此在Linux 4.3版本引入Ambient位。

(3)Effective:该权限集合包含了内核用于对线程进行权限检查的权限。内核会检查生效的权限集合,以确定线程是否被允许执行特定的特权操作。

(4)Bounding:capability bounding set 是一种机制,可用于限制execve()期间获取的能力。自Linux 2.6.25起,这是一个每个线程的能力集。在旧内核中,能力边界集是一个系统范围的属性,由系统上的所有线程共享。有关能力边界集的更多细节,请参考:Capability bounding set 这一章节。

(5)Ambient(自Linux 4.3版本引入):该权限集合包含了在执行非特权程序的execve()调用时会保留的权限。环境权限集合遵循一个原则,即只有同时在允许的和可继承的权限集合中的权限才能成为环境权限。可以使用prctl()系统调用直接修改环境权限集合。如果对应的允许的或可继承的权限被降低,环境权限也会被自动降低。当执行改变用户或组ID的程序(由于设置了set-user-ID或set-group-ID位)或具有设置了文件权限的程序时,环境权限集合会被清除。在执行execve()时,环境权限会被添加到允许的权限集合中,并赋予生效的权限集合。

“ambient"掩码的作用是满足大多数人对"inheritable”(可继承)掩码的期望。如果某个能力位在"inheritable"和"permitted"中没有设置,那么它永远也不会在"ambient"中设置。

如果你是非root用户但具有某种能力,你可以将其添加到"ambient"中。如果这样做,你的子进程将在"ambient"、"permitted"和"effective"中获得该能力。例如,你可以在"ambient"中设置CAP_NET_BIND_SERVICE,这样你的子进程就可以自动绑定低端口号。非特权用户可以创建用户命名空间,将自己映射到非零UID,并创建特权(相对于其命名空间而言)和非特权进程树。

通过fork()创建的子进程会继承其父进程的权限集合的副本。关于在execve()期间权限的处理,请参见:Transformation of capabilities during execve()。

使用capset(),线程可以操作自己的权限集合(请参见下面的说明)。

自Linux 3.2版本以来,文件/proc/sys/kernel/cap_last_cap公开了运行内核支持的最高权限的数值;这可以用于确定权限集合中可以设置的最高位。

# uname -r
3.10.0-1160.el7.x86_64
# cat /proc/sys/kernel/cap_last_cap
36

五、File capabilities

自内核版本2.6.24以来,内核支持使用setcap()将权限集合与可执行文件关联起来。文件权限集合存储在一个名为security.capability的扩展属性中(参见setxattr())。要写入该扩展属性,需要具有CAP_SETFCAP权限。文件权限集合与线程的权限集合一起确定了execve()后线程的权限。

文件权限集合分为三种:
(1)Permitted(以前称为 forced 的):无论线程的可继承权限如何,这些权限都会自动授予线程。

(2)Inheritable(以前称为 allowed 的):将此集合与线程的可继承集合进行逻辑与操作,确定在execve()后线程的允许集合中启用了哪些可继承权限。

(3)Effective:这不是一个集合,而只是一个单独的位。如果设置了该位,在execve()期间,线程的所有新允许的权限也会在生效集合中提升。如果未设置该位,在execve()之后,新的允许权限都不会出现在新的生效集合中。

启用文件的生效权限位意味着任何导致线程在execve()期间获取相应允许权限的文件允许或可继承权限(参见下面描述的转换规则),在其生效集合中也会获取该权限。因此,当为文件分配权限(使用setcap()、cap_set_file()、cap_set_fd())时,如果我们指定了任何权限的生效标志为启用状态,则对于所有其他启用了相应允许或可继承标志的权限,也必须指定生效标志为启用状态。

六、Transformation of capabilities during execve()

在execve()期间,内核使用以下算法计算进程的新权限:

P'(ambient) = (file is privileged) ? 0 : P(ambient)P'(permitted) = (P(inheritable) & F(inheritable)) |(F(permitted) & cap_bset) | P'(ambient)P'(effective) = F(effective) ? P'(permitted) : P'(ambient)P'(inheritable) = P(inheritable)    [i.e., unchanged]

其中:

P表示`execve(2)`之前线程的权限集合的值P'表示`execve(2)`之后的权限集合的值F表示文件的权限集合cap_bset是权限限制集合的值(下面描述)

特权文件是具有权限或设置了set-user-ID或set-group-ID位的文件。

解释说明:
P’(ambient):如果文件是特权文件,则设置为0,否则设置为P(ambient)的值。P(ambient)是execve()之前线程的环境权限集合。

P’(permitted):通过将P(inheritable)和F(inheritable)进行逻辑与操作,将可继承权限与文件的可继承权限进行逻辑与操作。然后,通过将F(permitted)和cap_bset进行逻辑与操作,将文件的允许权限与权限限制集合进行逻辑与操作。最后,将上述结果与P’(ambient)进行逻辑或操作,得到新的允许权限集合。

P’(effective):如果文件的生效权限位(F(effective))被设置,则P’(effective)等于P’(permitted);否则,P’(effective)等于P’(ambient)。

P’(inheritable):保持不变,即等于P(inheritable),即execve()之前线程的可继承权限集合。

七、Capabilities and execution of programs by root

当进程执行具有设置了set-user-ID-root(SUID)权限的程序,或者有效用户ID为0(即root)的进程执行程序时,权限处理遵循特定的规则,使用权限集合提供全能的root权限语义:
(1)文件的可继承和允许权限集合:如果正在执行的程序具有SUID权限或者进程的真实用户ID为0(即root),则文件的可继承和允许权限集合被设置为全1,表示启用了所有权限。这允许进程继承并拥有文件定义的所有权限。

(2)文件的生效权限位:如果正在执行的程序具有SUID权限,则文件的生效权限位被设置为1,表示新的允许权限也会在生效集合中提升。这确保进程获得文件定义的生效权限。

通过将这些规则与之前描述的权限转换相结合,结果是当进程执行SUID-root程序或有效UID为0的进程执行程序时,它会获取其允许和生效权限集合中的所有权限,除了被权限限制集合屏蔽的权限。权限限制集合充当了可以获取的权限的限制或屏蔽。

这些规则提供了与传统UNIX系统相同的语义,在传统UNIX系统中,root用户具有完全的权限,当执行特权程序时,所有与root用户相关的权限都会被授予。

值得注意的是,使用权限集合相比传统的二进制root/non-root区分提供了更精细和灵活的特权管理方法。它允许对授予进程的权限进行更细粒度的控制,通过限制特权用户执行的各个程序的权限,增强了安全性。

八、Capability bounding set

权限限制集合(capability bounding set)是Linux中的一种安全机制,用于限制进程在执行execve()系统调用时获取的权限和特权。它通过限制进程执行新程序时可以获取的能力集,来限制进程所能获得的特权。

权限限制集合的使用方式如下:
(1)在execve()期间,权限限制集合与文件的允许权限集合进行按位与运算,并将运算结果赋值给线程的允许权限集合。因此,权限限制集合限制了可执行文件可能被授予的允许权限。

(2)(自Linux 2.6.25起)权限限制集合作为一个限制的超集,限制了线程可以使用capset()将哪些权限添加到其可继承权限集合中。这意味着,如果一个权限不在限制集合中,线程就无法将该权限添加到其可继承权限集合中,即使它在其允许的权限中,也无法在execve()执行具有该权限在其可继承权限集合中的文件时保留该权限在其允许权限集合中。

权限限制集合的主要作用是减少潜在的安全风险,防止未经授权的访问或滥用特权操作。

权限限制集合的功能依赖于内核的配置。如果内核编译时启用了文件权限功能,那么权限限制集合可以用于删除特权。如果未启用文件权限功能,权限限制集合仍然存在,但只能屏蔽CAP_SETPCAP特权。

在Linux 2.6.25及以上的内核版本中,权限限制集合是线程级别的属性。在fork()系统调用期间,线程会从父线程继承权限限制集合,并在execve()调用时保持不变。可以通过prctl()系统调用以及相应的操作来修改权限限制集合。例如,可以使用PR_CAPBSET_DROP操作从权限限制集合中删除特权。

在执行execve()系统调用时,权限限制集合中的特权与文件的允许特权进行交集运算。运算结果成为进程的允许特权集合。这样可以确保进程获取的特权不会超出权限限制集合所允许的范围。

权限限制集合不会影响进程继承的特权集合。如果一个特权在继承的集合中存在但不在权限限制集合中,仍然可以通过执行继承集合中包含该特权的文件来获得该特权。

需要注意的是,一旦特权从权限限制集合中删除,就无法重新添加该特权。权限限制集合是单向限制,无法逆转。

通过仔细配置和管理权限限制集合,系统管理员可以实施更严格的安全策略,控制进程所获得的特权。这有助于减少系统的攻击面,最小化被入侵进程的潜在影响。

九、Effect of user ID changes on capabilities

用户ID的更改对能力(capabilities)的影响如下:
(1)能力清除:当从一个或多个实际(real)、有效(effective)或保存(saved)用户ID为0的情况过渡到所有这些ID都为非零值的情况时,所有能力将从允许(permitted)和有效能力集中清除。这确保在进程的特权状态发生变化时,与根用户(UID 0)相关的能力不会被保留。

(2)有效能力集清除:如果将有效用户ID从0(root)更改为非零值,则所有能力将从有效能力集中清除。这样做可以防止在有效用户ID更改为普通用户时保留与根用户相关的任何能力。

(3)允许能力集复制:如果将有效用户ID从非零值更改为0(root),允许能力集将被复制到有效能力集中。这意味着即使以特权状态运行,进程只能使用显式允许的能力。

(4)文件系统用户ID变更:当文件系统用户ID(FSUID)从0更改为非零值时,与文件系统操作相关的某些能力将从有效能力集中清除。这些能力包括CAP_CHOWN、CAP_DAC_OVERRIDE、CAP_DAC_READ_SEARCH、CAP_FOWNER、CAP_FSETID、CAP_LINUX_IMMUTABLE、CAP_MAC_OVERRIDE和CAP_MKNOD。相反,如果FSUID从非零值更改为0,则在允许能力集中启用的任何这些能力都将在有效能力集中启用,允许进程在操作文件系统时运用这些能力。

(5)PR_SET_KEEPCAPS:如果线程希望在将所有用户ID重置为非零值时防止其允许能力集被清除,可以使用prctl()系统调用中的PR_SET_KEEPCAPS操作。这允许进程在从特权状态(UID 0)过渡到普通用户状态时保留其能力。

这些机制确保根据用户ID的变化调整能力,保持系统的安全性和特权分离。它们有助于防止进程保留不必要的特权,并减少特权提升攻击的潜在影响。

十、 Programmatically adjusting capability sets

可以通过使用capget()和capset()系统调用来检索和更改线程的能力集。然而,为此目的,推荐使用libcap软件包提供的cap_get_proc()和cap_set_proc()函数。以下规则适用于对线程能力集的更改:

(1)如果调用者没有CAP_SETPCAP能力,则新的可继承能力集必须是现有可继承能力集和可允许能力集的组合的子集。换句话说,调用者只能在现有可继承能力集和可允许能力集的基础上添加或保留能力。

(2)(自Linux 2.6.25起)新的可继承能力集必须是现有可继承能力集和能力边界集的组合的子集。能力边界集是一个系统范围的能力集,限制了任何进程可以拥有的最大能力。

(3)新的可允许能力集必须是现有可允许能力集的子集。也就是说,线程无法获取当前没有的可允许能力。可允许能力集表示线程当前可以获得的最大能力。

(4)新的有效能力集必须是新的可允许能力集的子集。有效能力集表示当前线程正在使用的能力。通过设置有效能力集,线程可以根据需要激活或禁用特定的能力。

参考资料

https://cloud.tencent.com/developer/article/1529342

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144403.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

IntelliJ IDEA 左侧Commit栏不见了

1.点击File->Settings->Version Control->Commit 2.勾选Use non-modal commit interface

Git 学习(2)

Git 学习(2) 版本号 Git 中文件的版本号是 40 位十六进制的数字字符串,采用 SHA-1 加密算法计算获得 这样一方面可避免在合并时的冲突问题 另一方面可以用于文件定位,其中前两位表示文件夹,后 38 位表示文件 指令介…

阿里云网络、数据中心和服务器技术创新优势说明

阿里云服务器技术创新、网络技术创新、数据中心技术创新和智能运维:云服务器方升架构、自研硬件、自研存储硬件AliFlash和异构计算加速平台,以及全自研网络系统技术创新和数据中心巴拿马电源、液冷技术等技术创新说明,阿里云百科aliyunbaike.…

游戏设计模式专栏(一):工厂方法模式

引言 大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》,让糟糕的代码在潜移默化中升华,欢迎大家关注分享收藏订阅。 在游戏开发中,代码的组织和结构对于项目的可…

maven找不到jar包

配置settings.xml文件之后出现报错找不到jar包 先改maven设置: 然后在重新清理构建项目: 可以通过执行以下命令清理本地 Maven 仓库 mvn dependency:purge-local-repository

Java 实现前端数据的导出操作

前端 <el-button class"export" type"primary" icon"el-icon-download" click"exportData()">导出</el-button>exportData() {//data 操作data 变成后端需要的格式let data {capacityVos: resultVo}this.$confirm("…

服务器补丁管理软件

随着漏洞的不断上升&#xff0c;服务器修补是增强企业网络安全的典型特征。作为业务关键型机器&#xff0c;计划服务器维护的停机时间无疑是一件麻烦事。但是&#xff0c;借助高效的服务器补丁管理软件&#xff08;如 Patch Manager Plus&#xff09;&#xff0c;管理员可以利用…

FileManager/本地文件增删改查, Cache/图像缓存处理 的操作

1. FileManager 本地文件管理器&#xff0c;增删改查文件 1.1 实现 // 本地文件管理器 class LocalFileManager{// 单例模式static let instance LocalFileManager()let folderName "MyApp_Images"init() {createFolderIfNeeded()}// 创建特定应用的文件夹func cr…

JavaScript Web APIs第一天笔记

复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 **注意&#xff1a;**这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

数字乡村包括哪些方面?数字乡村应用介绍

数字乡村是指利用物联网、数字化和智能化技术&#xff0c;借助现代数字智能产品、高效信息服务和物联网基础设施&#xff0c;以提高农村居民生活质量&#xff0c;助力拓展经济发展前景。 创建数字村庄有助于缩小城乡社区之间的差距&#xff0c;保障每个人都能平等地享受科技发展…

flask_apscheduler实现定时推送飞书消息

需求场景&#xff1a; 实现一个flask服务&#xff0c;通过接口控制一个定时任务任务&#xff08;对酒店订房情况进行检查&#xff09;的开启和停止。要求定时任务完成后&#xff0c;可以通过飞书机器人推送任务完成的消息。 展现效果&#xff1a; 启动定时任务 关闭定时任务…

【2023研电赛】华东赛区一等奖:电动叉车永磁同步电机MTPA及弱磁控制研究

本文为2023年第十八届中国研究生电子设计华东赛区一等奖竞赛作品分享&#xff0c;参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&#xff01;&#xff0c;分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&a…

ChatGPT AIGC 总结Vlookup的20种不同用法

Vlookup是Excel中最常见的函数。接下来我们让ChatGPT,AIGC总结Vlookup函数的用法 。 1. 基本的VLOOKUP用法:=VLOOKUP("John", A2:B5, 2, FALSE)。在A2:B5范围中查找"John",返回与"John"在同一行的第2列的值。例如,查找员工姓名,返回员工ID。…

完整指南:如何使用 Node.js 复制文件

文件拷贝指的是将一个文件的数据复制到另一个文件中&#xff0c;使目标文件与源文件内容一致。Node.js 提供了文件系统模块 fs&#xff0c;通过该模块可以访问文件系统&#xff0c;实现文件操作&#xff0c;包括拷贝文件。 Node.js 中文件拷贝方法 在 Node.js 中&#xff0c;有…

Rust vs C++ 深度比较

Rust由于其强大的安全性受到大量关注&#xff0c;被认为C在系统编程领域最强大的挑战者。本文从语言、框架等方面比较了两者的优缺点。原文: Rust vs C: An in-depth language comparison Rust和C的比较是开发人员最近的热门话题&#xff0c;两者之间有许多相似之处&#xff0c…

K8sGPT,基于 AI 的云原生终极工具

随着人工智能和机器学习的兴起&#xff0c;企业和组织越来越多地寻找创新方法来利用这些技术来获得竞争优势。 该领域最强大的工具之一便是 K8sGPT&#xff0c;即基于 Kubernetes 的 GPT&#xff0c;它将 Kubernetes 编排的优势与 GPT 模型的高级自然语言处理能力结合在一起。 …

不同走向地下管线的地质雷达响应特征分析

不同走向地下管线的地质雷达响应特征分析 前言 以PVC管线为例&#xff0c;建立不同走向&#xff08;水平倾斜、垂直倾斜、水平相邻&#xff09;的三维管线地质模型&#xff0c;进行三维地质雷达数据模拟&#xff0c;分析不同走向地下管线的地质雷达响应特征。 文章目录 不同…

安卓手机使用油猴脚本教程

下载支持油猴脚本的浏览器 请现在应用商店下载 x浏览器 &#xff0c;如果自己手机应用商店没有的话&#xff0c;可以在官网下载安装包&#xff0c;然后手动安装。 x浏览器官网 应用图标&#xff1a; 导入油猴脚本 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1…

MIPI协议介绍-CPHY

MIPI协议概述 MIPI(Mobile Industry Processor Interface): 是MIPI联盟发起为移动应用处理器制定的开放标准.MIPI接口协议层主要包括CSI和DSI两种,其中CSI主要用于图像输出&#xff0c;如图像传感器等&#xff1b; DSI主要用于图像输入&#xff0c;如屏幕显示器等.对于camera而…

wps及word通配匹配与正则匹配之异同

前言 今天在chatgpt上找找有什么比赛可以参加。下面是它给我的部分答案&#xff0c;我想将其制成文档裱起来&#xff0c;并突出比赛名方便日后查找。 这时理所当然地想到了查找替换功能&#xff0c;但是当我启用时却发现正则匹配居然没有了&#xff0c;现在只有通配匹配了。 …