OPTEE TA介绍

news2024/11/18 0:30:49

前言

本文主要介绍OPTEE的TA(Trusted Applications),翻译自官方文档:Trusted Applications — OP-TEE documentation documentation (optee.readthedocs.io)


有两种方法可以实现可信应用程序 (TA):伪 TA 和用户模式 TA。用户模式 TA 是 GlobalPlatform API TEE 规范指定的功能齐全的受信任应用程序,这些只是人们在说“受信任的应用程序”时所指的那些,在大多数情况下,这是编写和使用首选的 TA 类型。

一、伪TA(Pseudo Trusted Applications)

伪TA不是受信任应用程序。伪 TA 不是特定实体。伪 TA 是一个接口。它是 OP-TEE Core 向其外部世界公开的接口:用于保护客户端受信任的应用程序和非安全的客户端实体。

这些直接实现到 OP-TEE 核心树中,例如:core/PTA,并与 OP-TEE core blob 一起构建并静态构建到其中。

OP-TEE中包含的伪TA已经是隐藏在“GlobalPlatform TA Client”API后面的OP-TEE安全特权级别服务。这些伪 TA 用于各种目的,例如特定的安全服务或嵌入式测试服务。

伪 TA 无法从 GlobalPlatform TEE 规范指定的 GlobalPlatform Core Internel API 支持中受益。这些 API 作为静态库提供给 TA,每个 TA 应链接(“libutee”),并通过syscalls调用 OP-TEE 核心服务。由于OP-TEE核心不与libutee链接,伪TA只能使用OP-TEE核心内部API和例程。

由于伪 TA 在与 OP-TEE 核心代码本身相同的特权执行级别上运行,因此根据用例的不同,这可能是可取的,也可能是不可取的。

在大多数情况下,非特权(用户模式)TA 是最佳选择,而不是将代码直接添加到 OP-TEE core。但是,如果您决定最好像这样直接在 OP-TEE core中处理您的应用程序,您可以将 core/pta/stats.c 视为模板,并基于此将伪 TA 添加到同一目录中的 sub.mk 中

二、用户模式TA(User Mode Trusted Applications)

用户模式TA由Secure World中的 OP-TEE core加载(映射到内存中),当富执行环境 (REE) 中的某些内容想要与该特定应用程序 UUID 通信时。它们以比 OP-TEE 核心代码更低的 CPU 权限级别运行。在这方面,它们与在 REE 中运行的常规应用程序非常相似,只是它们在Secure World中执行。

TA受益于全球平台 TEE 规范指定的 GlobalPlatform TEE Internel Core API。有几种类型的用户模式 TA,它们的存储方式不同。

三、TA位置

普通 TA(用户模式)可以驻留且从不同位置加载。OP-TEE 目前支持三种方式。

1、Early TA

所谓的Early TA 实际上与 REE FS TA 相同,但它们不是从正常世界文件系统加载的,而是链接到 TEE core blob 中的特殊数据部分。因此,它们甚至在 tee supplicant和 REE filesystem出现之前就可用。请在early TA summit中找到更多详细信息。

2、REE filesystem TA

它们由一个 ELF 文件组成,经过签名和选择性加密,以 TA 的 UUID 和 .ta后缀命名。它们是独立于 OP-TEE core boot-time blob生成的,尽管在生成它们时它们使用相同的生成系统,并使用原始  OP-TEE core blob 生成的密钥进行签名。

由于 TA 已签名并可选择使用脚本/sign_encrypt.py进行加密,因此它们能够存储在不受信任的 REE filesystem中,并且tee supplicant将负责传递它们以由Secure World OP-TEE core检查和加载。

A.REE-FS TA 回滚保护

OP-TEE core在安全存储中维护一个ta_ver.db文件,以检查从 REE-FS 加载的 REE TA 版本,以防止任何 TA 版本降级。TA 版本可以通过 TA  build option进行配置:CFG_TA_VERSION=<unsigned integer>。

注意:此处的回滚保护仅在 CFG_RPMB_FS=y 时有效

B.REE-FS TA 格式

REE 文件系统 TA 有三种格式:

自版本 3.7.0 起,构建脚本无法再创建已签名且未加密的旧版 TA。

引导 TA使用原始 OP-TEE core blob 生成的密钥进行签名,未加密。

加密的 TA,先签名再加密后 MAC,当 CFG_ENCRYPT_TA=y 时用 TA_ENC_KEY 加密。在 OP-TEE 运行时,用于解密 TA 的对称密钥必须通过覆盖 API 以平台特定的方式提供:

TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer,
                                  size_t len);

C.REE-FS TA 头结构

所有 REE 文件系统 TA 都有通用的头,struct shdr,定义为:

enum shdr_img_type {
        SHDR_TA = 0,
        SHDR_BOOTSTRAP_TA = 1,
        SHDR_ENCRYPTED_TA = 2,
};

#define SHDR_MAGIC      0x4f545348

/**
 * struct shdr - 签名头
 * @magic:      magic number必须与SHDR_MAGIC匹配
 * @img_type:   image type, values 通过enum shdr_img_type定义
 * @img_size:   图像大小(以字节为单位)
 * @algo:       算法,由 TEE 内部 API 规范形如TEE_ALG_XXX定义的公钥算法
 * @hash_size:  签名哈希的大小
 * @sig_size:   签名的大小
 * @hash:       图像的哈希
 * @sig:        hash签名
 */
struct shdr {
        uint32_t magic;
        uint32_t img_type;
        uint32_t img_size;
        uint32_t algo;
        uint16_t hash_size;
        uint16_t sig_size;
        /*
         * 注释掉的元素用于可视化结构体的动态布局部分。
         * 哈希通过宏SHDR_GET_HASH访问,签名通过宏SHDR_GET_SIG
         *
         * uint8_t hash[hash_size];
         * uint8_t sig[sig_size];
         */
};

#define SHDR_GET_SIZE(x)        (sizeof(struct shdr) + (x)->hash_size + \
                                 (x)->sig_size)
#define SHDR_GET_HASH(x)        (uint8_t *)(((struct shdr *)(x)) + 1)
#define SHDR_GET_SIG(x)         (SHDR_GET_HASH(x) + (x)->hash_size)

字段img_type为 TA 的类型,如果它是SHDR_TA(0),则它是旧版 TA。如果是SHDR_BOOTSTRAP_TA(1),则为引导 TA。

字段algo为使用的算法。用于对 TA 进行签名的脚本当前使用TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 (0x70004830)。这意味着RSA具有PKCS#1v1.5填充和SHA-256哈希函数。OP-TEE 接受任何 TEE_ALG_RSASSA_PKCS1_* 算法。

对于引导 TA,结构 shdr 后跟一个子标题,结构体shdr_bootstrap_ta定义为:

/**
 * struct shdr_bootstrap_ta - bootstrap TA subheader
 * @uuid:       TA的UUID
 * @ta_version: TA的版本
 */
struct shdr_bootstrap_ta {
        uint8_t uuid[sizeof(TEE_UUID)];
        uint32_t ta_version;
};

字段 uuid 和 ta_version 允许在加载 TA 时执行额外的检查。目前仅检查 uuid 字段。

对于加密的 TA,结构 shdr 后跟一个子标题,结构shdr_bootstrap_ta后跟另一个子标题,结构shdr_encrypted_ta定义为:

/**
 * struct shdr_encrypted_ta - encrypted TA header
 * @enc_algo:   经过身份验证的加密算法,由 TEE 内部 API 规范中的对称密钥算法 TEE_ALG_* 定义
 * @flags:      经过身份验证的加密标志
 * @iv_size:    初始化向量的大小
 * @tag_size:   身份验证标记的大小
 * @iv:         初始化向量
 * @tag:        身份验证标记
 */
struct shdr_encrypted_ta {
        uint32_t enc_algo;
        uint32_t flags;
        uint16_t iv_size;
        uint16_t tag_size;
        /*
         * 注释掉的元素用于可视化 struct.iv 的布局动态部分通过宏SHDR_ENC_GET_IV访问,标记通过宏SHDR_ENC_GET_TAG访问
         *
         * uint8_t iv[iv_size];
         * uint8_t tag[tag_size];
         */
};

字段enc_algo告诉所使用的算法。用于加密 TA 的脚本当前使用 TEE_ALG_AES_GCM (0x40000810)。OP-TEE内核也接受TEE_ALG_AES_CCM算法。

字段flags支持单个标志来告知加密密钥类型,该类型定义为:

#define SHDR_ENC_KEY_TYPE_MASK  0x1

enum shdr_enc_key_type {
        SHDR_ENC_KEY_DEV_SPECIFIC = 0,
        SHDR_ENC_KEY_CLASS_WIDE = 1,
};

D.REE-FS TA 二进制格式

TA 二进制文件遵循 ELF 文件,该文件通常被剥离为附加符号等,加载 TA 时将被忽略。

旧版 TA 二进制文件的格式为

hash = H(<struct shdr> || <stripped ELF>)
signature = RSA-Sign(hash)
legacy_binary = <struct shdr> || <hash> || <signature> || <stripped ELF>

 引导 TA 二进制文件的格式为:

hash = H(<struct shdr> || <struct shdr_bootstrap_ta> || <stripped ELF>)
signature = RSA-Sign(<hash>)
bootstrap_binary = <struct shdr> || <hash> || <signature> ||
                   <struct shdr_bootstrap_ta> || <stripped ELF>

加密的 TA 二进制文件的格式为:

nonce = <unique random value>
ciphertext, tag = AES_GCM(<stripped ELF>)
hash = H(<struct shdr> || <struct shdr_bootstrap_ta> ||
         <struct shdr_encrypted_ta> || <nonce> || <tag> || <stripped ELF>)
signature = RSA-Sign(<hash>)
encrypted_binary = <struct shdr> || <hash> || <signature> ||
                   <struct shdr_bootstrap_ta> ||
                   <struct shdr_encrypted_ta> || <nonce> || <tag> ||
                   <ciphertext>

E.使用subkeys进行验证

可以使用subkeys或subkeys链来验证 TA。这允许在不分发根密钥的情况下委派 TA 签名。使用子项签名的 TA 仅限于子项的 UUID-V5 命名空间,以避免 TA UUID 与不同的子项发生冲突。

SHDR_SUBKEY是一种启用公钥链的标头。公钥根密钥用于验证第一个公钥subkey,然后用于验证下一个公钥subkeys,依此类推。

最后使用最后一个子项验证 TA。所有这些标头都添加到 TA 二进制文件的前面,因此验证 TA 所需的所有内容在加载到内存中时都可用。

F.加载REE-FS TA

REE TA 使用将 REE TA 加载到不安全共享内存中的系列或 RPC 加载到共享内存中。有效负载内存通过 TEE 请求方分配,稍后在释放先前分配的非安全共享内存中将 TA 加载到安全内存中时释放。

 将 REE TA 加载到不安全的共享内存中

 释放以前分配的不安全共享内存

3、Secure Storage TA

这些存储在安全存储中。元数据存储在所有已安装 TA 的数据库中,实际的二进制文件作为不受信任的 REE 文件系统(flash)中的单独文件进行加密和完整性保护。在加载这些 TA 之前,必须先安装它们,这是可以在初始部署期间或稍后阶段完成的操作。

出于测试目的,测试程序xtest可以使用以下命令将TA安装到安全存储中:

$ xtest --install-ta

存储在安全存储中的 TA 保存在 TA 数据库中。TA 数据库由一个名为 dirf 的单个文件组成.db该文件存储在基于 REE filesystem的安全存储或 RPMB 中。该文件与安全存储中的任何其他对象一样加密和完整性保护。TA 本身不存储在 dirf.db 中,而是存储在加密和完整性保护的 REE 文件系统中。其中一个原因是 TA 可能非常大,只有几兆字节,而安全存储旨在仅容纳以千字节为单位的小对象。

DIRF.db结构tadb_entry数组的组成,定义为:

/*
 * struct tee_tadb_property
 * @uuid:       可信应用程序 (TA) 或安全域 (SD) 的 UUID
 * @version:    TA 或 SD 的版本
 * @custom_size:自定义属性的大小,附加到加密的 TA 二进制文件前面
 * @bin_size:   二进制 TA 的大小
 */
struct tee_tadb_property {
        TEE_UUID uuid;
        uint32_t version;
        uint32_t custom_size;
        uint32_t bin_size;
};

#define TADB_IV_SIZE            TEE_AES_BLOCK_SIZE
#define TADB_TAG_SIZE           TEE_AES_BLOCK_SIZE
#define TADB_KEY_SIZE           TEE_AES_MAX_KEY_SIZE

/*
 * struct tadb_entry - TA database entry
 * @prop:        TA的属性
 * @file_number: 加密的 TA 存储在 <file_number>.ta 中
 * @iv:          身份验证加密的初始化向量
 * @tag:         用于验证身份验证加密 TA 的标记
 * @key:         用于解密 TA 的密钥
 */
struct tadb_entry {
        struct tee_tadb_property prop;
        uint32_t file_number;
        uint8_t iv[TADB_IV_SIZE];
        uint8_t tag[TADB_TAG_SIZE];
        uint8_t key[TADB_KEY_SIZE];
};

UUID 仅由零组成的条目无效,将被忽略。file_number字段表示存储在 REE 文件系统中的文件的名称。文件名由附加 .ta 的file_number的十进制字符串表示形式组成,或者如果要打印:printf(“%u.ta”, file_number)。

TA 使用 iv 和密钥字段初始化的身份验证加密算法 AES-GCM 进行解密,完成解密时使用标签字段。

通过打开 dirf 并在结构tadb_entry类型元素中扫描 TA .db直到找到匹配的 UUID 来查找 TA。

四、加载和准备 TA 以执行

用户模式 TA 使用用户模式 ELF 加载器 ldelf 以相同的方式加载到最终内存中。不同的 TA 位置具有指向 ldelf 的通用接口,这使得用户模式操作与 TA 的存储方式相同。

TA 将加载到准备 TA 以执行中的安全内存中。

准备 TA 执行

在 ldelf 返回准备执行的 TA 后,如果使用 dlopen() 和朋友,它仍然保留在内存中以服务于 TA。如果 TA 通过中止终止,ldelf 还用于转储堆栈跟踪和详细的内存映射。

Linux 用户空间中客户端应用程序的整个流的高级视图,其中会话被打开到 TA,在打开会话到 TA 中。

向 TA 打开会话

五、TA属性

1、GP属性

标准 TA 属性必须通过宏中的属性标志定义 TA_FLAGS user_ta_header_defines.h

A.单实例

“gpd.ta.singleInstance” 是 TA 的bool属性。此属性定义是必须创建 TA 的一个实例并接收所有打开的会话请求,还是必须为每个传入的打开会话请求创建新的特定 TA 实例。OP-TEE TA 标志TA_FLAG_SINGLE_INSTANCE设置为此属性的配置。如果TA_FLAGS设置位TA_FLAG_SINGLE_INSTANCE,则bool属性设置为 true,否则bool属性设置为 false。

B.多会话

“gpd.ta.multiSession” 是 TA 的bool属性。此属性定义 TA 实例是否可以处理多个会话。如果禁用,则 TA 实例仅支持一个会话。在这种情况下,如果 TA 已经打开了会话,则任何打开的会话请求都将返回繁忙错误状态。

注意:如果 TA 不是单实例 TA,则此属性毫无意义。

OP-TEE TA 标志TA_FLAG_MULTI_SESSION设置为此属性的配置。如果TA_FLAGS设置位TA_FLAG_MULTI_SESSION,则bool属性设置为 true,否则bool属性设置为 false。

C.Keep Alive

“gpd.ta.instanceKeepAlive” 是 TA 的bool属性。此属性定义当关闭朝 TA 打开的所有会话时,是否必须销毁创建的 TA 实例。如果启用了该属性,则 TA 实例一旦创建(在第一个打开会话请求时),将永远不会删除,除非重新启动 TEE 本身(启动/重新启动)。

注意:如果 TA 不是单实例 TA,则此属性毫无意义。

OP-TEE TA 标志TA_FLAG_INSTANCE_KEEP_ALIVE设置为此属性的配置。如果 TA_FLAGS 位设置为 TA_FLAG_INSTANCE_KEEP_ALIVE,则bool属性设置为 true,否则bool属性设置为 false。

D.堆大小

“gpd.ta.dataSize” 是 TA 的 32 位整数属性。此属性定义 TA 分配池的大小(以字节为单位),TEE_Malloc() 和友元在其中分配内存。属性的值必须由 user_ta_header_defines.h 中的宏TA_DATA_SIZE定义。

E.栈大小

“gpd.ta.stackSize” 是 TA 的 32 位整数属性。此属性定义用于 TA 执行的堆栈的大小(以字节为单位)。属性的值必须由 user_ta_header_defines.h 中的宏TA_STACK_SIZE定义。

2、属性扩展

A.安全数据路径标志

TA_FLAG_SECURE_DATA_PATH是TA_FLAGS支持的位标志。此属性标志声明来自 OP-TEE OS 的安全数据支持。请参阅 OP-TEE OS 以获取安全数据路径支持。未在 TA_FLAGS 值中设置TA_FLAG_SECURE_DATA_PATH的 TA 将无法处理与安全数据路径缓冲区相关的内存引用调用参数。

B.缓存维护标志

TA_FLAG_SECURE_DATA_PATH是TA_FLAGS支持的位标志。此属性标志声明来自 OP-TEE OS 的安全数据支持。请参阅 OP-TEE OS 以获取安全数据路径支持。未在 TA_FLAGS 值中设置TA_FLAG_SECURE_DATA_PATH的 TA 将无法处理与安全数据路径缓冲区相关的内存引用调用参数。

C.已弃用的属性标志

旧版本的 OP-TEE 用于定义扩展属性标志,这些标志已弃用且对当前 OP-TEE 毫无意义。这些是TA_FLAG_USER_MODE的,TA_FLAG_EXEC_DDR的和TA_FLAG_REMAP_SUPPORT的。

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

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

相关文章

Speedoffice(word)如何输入特殊符号?

Word文档有时需要输入人民币单位“元”&#xff08;&#xff09;的符号&#xff0c;那么怎么打出来了&#xff0c;以我最常用的Speedoffice为例和大家分享一下方法。步骤&#xff1a;1&#xff0c;首先运行office软件&#xff0c;新建一份word&#xff0c;找到“插入”菜单栏里…

再学C语言33:函数——地址运算符

C中最重要、最复杂的概念之一就是指针&#xff08;pointer&#xff09; 指针是用于存储地址的变量 例如&#xff1a;scanf()函数中使用地址作为参数 当需要改变调用函数中的某个值时&#xff0c;任何被调用的无返回值的C函数都需要使用地址参数完成该任务 一、地址运算符&a…

c语言重点

1、以下代码循环几次&#xff1f;&#xff08;面试题&#xff09; void test(){int i; // 局部变量 i 的值是不确定的for(;i<10;i){;} }答案是---------不确定&#xff0c;在 c 语言中局部变量 i 没有初始化&#xff0c;值是不确定的&#xff0c;所以 i 的值可能是…

GeoHash 的编码方法

对一组经纬度进行 GeoHash 编码时&#xff0c;我们要先对经度和纬度分别编码&#xff0c;然后再把经纬度各自的编码组合成一个最终编码。 对于一个地理位置信息来说&#xff0c;它的经度范围是[-180,180]。GeoHash 编码会把一个经度值编码成一个 N 位的二进制值&#xff0c;我…

MySQL进阶篇之存储引擎

01、存储引擎 1.1、MySQL体系结构 连接层 最上层是一些客户端和链接服务&#xff0c;主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 服务层 第二层架构主要完成大多数的核心服务功能&#xff0c;如SQL…

重要的字符(串)函数的使用及其实现

目录 字符串函数注意点 1、\0 2、适当使用const修饰 3、多使用assert断言 4、库函数不可能完全安全 1、求字符串长度strlen 1、计数实现 2、递归实现 3、指针相减求元素个数 2、长度不受限制的字符串函数 1、strcpy 2、strcat 3、strcmp 3、长度受限制的字符串函数…

ESP32设备驱动-MLX90614红外测温传感器驱动

MLX90614红外测温传感器驱动 1、MLX90614介绍 MLX90614 是一款用于非接触式温度测量的红外温度计。IR 敏感型热电堆检测器芯片和信号调节 ASIC 都集成在同一 TO-39 罐封装中。MLX90614 集成有低噪声放大器、17 位 ADC 和强大的 DSP 单元,因此温度计兼具高精度和高分辨率。 …

少儿Python每日一题(22):杨辉三角

原题解答 本次的题目如下所示: 杨辉三角形又称Pascal三角形,它的第i+1i+1行是的展开式的系数。 它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。 下面给出了杨辉三角形的前4行: 1 1 1 1 2 1 1 3 3 1 给出n,输出它的前n行。 输入: 输入包含一个数n。 输出…

学习CSS3,使用双旋转实现福到了的迎春喜庆特效

春节快到了&#xff0c;因为疫情已经好久没有回老家了&#xff0c;今年终于可以回家过年了&#xff0c;我已经抑制不住自己激动的心情了。因此&#xff0c;我利用css3的旋转做了一个福到了的特效&#xff0c;而且是双旋转哦。 目录 1、实现思路 2、大红纸的渲染过程 3、错误…

【自学Python】Python运算符优先级

Python运算符优先级 Python运算符优先级教程 我们知道&#xff0c;在数学运算中&#xff0c;有 “先乘除后加减” 的运算规则&#xff0c;在我们程序语言中一样有运算符的优先级问题&#xff0c;来决定我们运算的顺序问题&#xff0c;这就是运算符的优先级。 即所谓运算符的…

C++STL之set与map的使用

本文目录前言一、关联式容器二、键值对(pair)三、树形结构的关联式容器1.set1.1set的介绍1.2set的使用1.2.1set的模板参数列表1.2.2set的构造(1)构造空的set(2)以数组的形式构造(3)用迭代器区间进行构造(4)拷贝构造1.2.3set的迭代器(1)iterator begin()(2)iterator end()(3)con…

一天变现100w就是这么简单!呆头鹅批量剪辑软件批量剪辑带货视频

呆头鹅剪辑是一款全自动的视频剪辑软件&#xff0c;包含剪辑、合成、去重、特效、配音、字幕、水印、后期处理、自动生成片头等功能&#xff0c;可以用于视频批量搬运&#xff0c;给视频增加特效&#xff0c;图片合成视频&#xff0c;视频混剪&#xff0c;自动加配音字幕&#…

Linux一看就会——make/Makefile

Linux一看就会——make/Makefile 背景 1.会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力。 2.一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的 规则来指定&#xff0c;哪…

分享126个ASP源码,总有一款适合您

ASP源码 分享126个ASP源码&#xff0c;总有一款适合您 126个ASP源码DownLoad链接&#xff1a;https://pan.baidu.com/s/1wekzBbNE6JSFWtyLb_CdQg?pwdu1e0 提取码&#xff1a;u1e0 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下..…

I16-python中的Counter类

在很多场景中经常会用到统计计数的需求&#xff0c;比如在实现 KNN算法时统计 k 个标签值的个数&#xff0c;进而找出标签个数最多的标签值作为最终 kNN 算法的预测结果。Python内建的 collections 集合模块中的 Counter 类能够简洁、高效的实现统计计数。Counter 是 dict 字典…

Unity 3D 三维模型简介||

Unity 3D 三维模型简介 三维模型是用三维建模软件建造的立体模型&#xff0c;也是构成 Unity 3D 场景的基础元素。 Unity 3D 几乎支持所有主流格式的三维模型&#xff0c;如 FBX 文件和 OBJ 文件等。 开发者可以将三维建模软件导出的模型文件添加到项目资源文件夹中&#xf…

【服务器数据恢复】意外断电导致linux服务器故障的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某品牌730服务器&#xff0c;linux操作系统。 机房意外断电导致服务器部分文件丢失。 服务器数据备份&故障分析&#xff1a; 1、将linux服务器连接到准备好的数据恢复服务器上&#xff0c;以只读模式对服务器数据做镜像备份&#…

geoserver 图层访问权限控制

目录 一、环境 二、问题 三、设置登录才能访问图层 ①、创建身份验证过滤器 ②、创建过滤器 ③、校验 ④、过滤后的问题 一、环境 geoserver2.17.0 二、问题 1、geoserver图层不需要登录就能访问&#xff0c;是否存在安全隐患&#xff1f; 答&#xff1a;会有一定的安全隐…

【Linux操作系统】计算机体系结构和操作系统与进程概念深入理解

文章目录一.现代计算机体系结构1.和冯诺依曼体系结构的异同2.计算机的五大核心部件3.举例子:“我爱你”4.CPU,内存,磁盘的联系a.三者读写速度对比b.规定:CPU不直接和外设打交道二.操作系统1.操作系统三段论2.系统调用接口3.用户操作接口三.进程1.什么是进程?2.PCB3.查看进程4.…

222.完全二叉树的节点个数 |递归优化思路 + 复杂度分析

完全二叉树的节点个数 leetcode : https://leetcode.cn/problems/count-complete-tree-nodes/ 递归思路 递归的思路很简单, 假设们要统计一棵树的节点数, 那么 只要统计根节点的左子树的节点数, 和右子树的节点数加上根节点即可 那么, 假设我们要统计左子树的节点数, 其实就…