Android - 深入浅出理解SeLinux

news2024/11/17 23:31:09

1. 概述

官方文档:

https://source.android.com/docs/security/features/selinux

https://source.android.com/docs/security/features/selinux/images/SELinux_Treble.pdf

Your visual how-to guide for SELinux policy enforcement | Opensource.com

SeLinux(Security-Enhanced Linux)是一个标签系统(labeling system)。每个进程都有一个label(称为process label),每个文件系统所涵盖的文件/目录、网络端口、设备等对象也有一个lable(称为Object label)。SeLinux通过编写规则来控制一个process label对一个Object label的访问,这个规则称之为策略(Policy)。SeLinux的这种安全机制称为Mandatory Access Control (MAC),是在内核层实现的。

在标准的Linux上,也就是未实施SeLinux的Linux上,传统的访问控制是通过owner/group + permission flags(比如rwx)实现的,称之为Discretionary Access Control (DAC).

SeLinux和传统的DAC不是替代的关系,而是并行的关系。两者同时在起作用。之所以出现SeLinux,是因为传统DAC的安全机制过于粗粝,而Selinux提供了更为细致和安全的访问控制。简言之,传统DAC机制下,一旦你获得了root权限,将无所不能,但在SeLinux的机制下,即使获得了root权限,也仍然需要遵循已经设置好的访问策略,只有指定的进程才可以访问指定的文件。

SeLinux有两种运行模式:

  • Permissive mode:当访问并未授权时,不会阻止访问,但会打印log
  • Enforcing mode:当访问未被授权时,会阻止访问,并且会打印log

log将出现在dmesg和logcat。

除了可以对整体进行模式设置,也可以针对某个进程单独设置某个模式,除此之外的进程使用全局模式。

设计

SeLinux在Android 4~7和Android 8以后采用了不同的设计

Android 4~7上,SeLinux的策略是作为一个整体来编译和更新的;

Android 8及以后,SeLinux采用了模块化、动态化设计,Platform(可以理解为AOSP的部分)、Non-Platform(vendor、odm、oem的部分,这里总体称为vendor部分)的SeLinux策略分别独立编译、升级。

附一张Android设备的架构图:

编译后会生成对应的img文件

● system.img. Contains mainly Android framework.

● boot.img. (kernel/ramdisk) Contains Linux kernel + Android patches.

● vendor.img. Contains SoC-specific code and configurations.

● odm.img. Contains device-specific code and configurations.

● oem.img. Contains OEM/carrier-related configurations and customizations.

● bootloader. Brings up the kernel (vendor-proprietary).

● radio. Modem (proprietary).

Android 8以后,SeLinux的策略文件可以伴随相应的img独立编译或者OTA。

2. 概念

什么是标签(Label)?怎么基于Label对访问进行控制?

先抛开Label这个概念不说。所谓SeLinux里的访问控制,就是判定一个Source有没有权限去访问Target。这里的Source一般就是进程,Target最长见的就是文件系统(比如文件、目录、socket、设备等等),当然还有其他类型的Target。换句话说,SeLinux的机制就是通过读取一个“规则”,来控制一个进程有没有权限去访问一个文件(或其他类型)。

上面说的“规则”,在SeLinux里的术语叫做Policy(策略)或叫Access Vector Rule。是可以由AOSP和厂商、供应商来编写的。

上面的Source,还叫做Subject(主体)

上面的Target,还叫做Object(对象或客体)

Label、Source、Target、Subject、Object,这些都不重要, 在实际语法中并没有相关关键词,只要各种资料里出现这些词的时候知道其所指就可以。

2.1 规则Policy Rule(或叫Access Vector Rule)

策略规则的语法为:

allow source target:class permissions;
  • Source - The type (or attribute) of the subject of the rule. Who is requesting the access?(是谁在请求访问一个资源)
  • Target - The type (or attribute) of the object. To what is the access requested?(被访问的对象)
  • Class - The kind of object (e.g. file, socket) being accessed.(被访问者的类型)
  • Permissions - The operation (or set of operations) (e.g. read, write) being performed.(对Target具体要做什么操作?比如对被访问者是文件来说,是要读、写它还是其他操作?)

具体例子如下:

allow sample_app app_data_file:file { read write };

这个例子是说,允许sample_app这个进程去访问app_data_file(它是一个file类型,也就是文件),允许的操作是read和write。

而其实这里的sample_app并不是一个真正的具体的进程名,而是在系统编译阶段就定义好的一个标签(Label),一些真正的进程被映射到sample_app这个标签上,那么在执行上面规则的时候,其实生效的、有权限访问app_data_file的是所有映射了sample_app标签的那些进程。同样的,app_data_file也不是一个具体的文件名。它也是一个提前声明了的标签,一些真正的文件被映射到这个标签上,sample_app有权访问的是所映射的这些文件。

从这里看出来,有别于传统DAC的Owner、Group、Permissions 的控制方式,所谓的“基于标签系统”的SeLinux,就是这种通过声明标签的方式来表述访问规则的。

标签只是一种概念性的东西,具体体现在策略文件里,则是抽象成了Type、Attribute、Class、Permissions这些具体关键字。

2.2 规则里的关键字说明

以下面这个规则举例

allow sample_app app_data_file:file { read write };

Rule Name

上面规则示例中,allow就是Rule Name的一种。SeLinux有多种RuleName:

  • allow:表示允许Source对Target执行许可的操作
  • neverallow:表示不允许Source对Target执行制定的操作
  • auditallow:表示允许操作并记录访问决策信息
  • dontaudit:表示不记录违反规则的决策信息,切违反规则不影响运行。

其中allow是用的最多的。

Type

上面的示例中,sample_app、app_data_file都是一个Type。简单理解就是将一个或几个进程声明为Type A, 将一个或多个文件声明为Type B。那么在控制这个进程有没有权限访问这个文件的时候,只用A和B来表示就可以了。

这样做有什么好处?“一类进程”总比具体的“一个进程”要灵活的多。把多个进程声明为同一个Type,那么在写规则的时候只要描述这个Type,那么这个Type对应的所有进程都会生效。文件或其他对象也是同样的。

也就是说,在规则中描述Source能不能访问Target,是通过Type来表述的。

Type是厂商或供应商可以自定义的

Attribute

将多个Type归为一组,就是一个Attribute。

通俗的说,把一些进程声明为Type,但是多个Type有某种共通的特性,就可以把这些Type声明为同一个Attribute。在描述规则的时候,可以将Source或者Target指定为一个Attribute而不是Type,这样所有属于这个Attribute的Type都生效。

AOSP本身内置了一些Attribute,而这些Attribute很多都是约定俗称的固定含义。比如:

domain

所有进程的type必须归属于domain。domain因此成了进程type的常见表述。

file_type

所有文件type都归属于file_type

...

AOSP内置的Attribute见

platform/system/sepolicy/public/attributes

platform/system/sepolicy/private/attributes

platform/system/sepolicy/prebuilts/api/[version]/public/attributes

platform/system/sepolicy/prebuilts/api/[version]/private/attributes

Class

上面示例中,“:file”就是一个Class。简单说就是将某些被访问对象归为一种Class,比如说被访问的是文件,Class一般就是file,如果是目录,Class就是dir,如果是socket,Class就是socket等等。Class是AOSP内定义好的,一般不需要自定义

具体有那些Class,可见源码platform/system/sepolicy/private/security_classes

Class是用来做什么的?其实是与Permissions相关的。

Permissions

即示例中的 { read write }。表示具体可以做什么操作。不同的Class有不同的Permissions集合。罗列一些Class对应Permission(非完整)

Class

Permission

file

ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton

directory

add_name remove_name reparent search rmdir open audit_access execmod

socket

ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind

filesystem

mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget

process

fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate

security

compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy

capability

chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap

MORE

AND MORE

可以从对应的Class中选取任意个Permission

Class与Perimssion的完整映射具体见源码:kernel/arm64/security/selinux/include/classmap.h

示例

以控制狗是否有权吃猫粮狗粮为例。

有一个狗叫小黄, 一种狗粮叫“狗粮A”。

现在声明一个Type叫dog,一个Type叫dog_chow,系统本身内置了Class叫food,food对应的permissions里包含了eat这个权限。

随后将小黄映射到dog这个type,将狗粮A映射到dog_chow这个type

这样,在添加了这样一条规则后,小黄就有权限去吃狗粮A了:

allow dog dog_chow:food eat;

此时如果还有一只狗小白,那么可以将小白映射到dog这个type,这样小白也可以有权限吃狗粮A。

2.3 Context

上面所说的“映射”,即将一个进程关联到一个Type,或者将一个文件关联到一个Type,是通过context来完成的。

进程Context(seapp_contexts)

一个进程的Context条目可能如下:

user=_app isPrivApp=true name=com.android.vzwomatrigger domain=vzwomatrigger_app type=privapp_data_file levelFrom=all

user=_app代表这是一个常规的app;

isPrivApp=true代表这是一个预置app;

name=com.android.vzwomatrigger 指定了进程名

domain=vzwomatrigger_app 将进程名关联到一个type

type=privapp_data_file 这是一个文件type,指定了app的data directory目录所属的type

levelFrom=all MLS/MCS的level相关

AOSP内置进程Context见platform/system/sepolicy/private/seapp_contexts

供应商或厂商要定义自己的seapp_context,将在/vender下相应目录添加

文件Context

一个文件的Context可能这样:

/system/bin/bcc                 u:object_r:rs_exec:s0

/system/bin/bcc 指的是具体文件

u:object_r:rs_exec:s0是一个security context。其中的rs_exec为type。这样文件和type就进行了关联

Security Context

其格式为:

user:role:type:sensitivity[:categories]

在Android中,

user是固定的,永远为u

role是固定的,访问者(称subject或source)永远为r;被访问者(称object或target)永远为object_r。一般情况下,进程一方就是subject,文件一方就是object,所以一般进程的role

type为与文件关联的type

sensitivity是固定的,永远为s0

categories是Multi-Level Security (MLS) 协议,用来隔离一个app的data,防止被另一个app访问,或者隔离不同用户间对同一个app data的访问。

AOSP内置的文件Context见platform/system/sepolicy/private/file_contexts

seinfo

seapp_context除了可以一个具体应用映射一个domain也可以seinf映射domainmac_permissions.xml定义seinfo根据app所属signature分配一个seinfo

比如

platform/system/sepolicy/private/mac_permissions.xml

<!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
      <seinfo value="platform" />
    </signer>

    <!-- Sdk Sandbox key -->
    <signer signature="@SDK_SANDBOX" >
      <seinfo value="sdk_sandbox" />
    </signer>

    <!-- Bluetooth key in AOSP -->
    <signer signature="@BLUETOOTH" >
      <seinfo value="bluetooth" />
    </signer>

    <!-- Media key in AOSP -->
    <signer signature="@MEDIA" >
      <seinfo value="media" />
    </signer>

    <signer signature="@NETWORK_STACK" >
      <seinfo value="network_stack" />
    </signer>

也就是所有拥有PLATFORM signatureapp拥有platform这个seinfoseapp_context可以如下配置

user=radio seinfo=platform domain=radio type=radio_data_file

所有拥有platform签名并且配置具体contextapp将遵循其seinfo platform规则

untrusted_app

配置seinfo配置seapp_contextapp默认untrusted_app各级seapp_context也有untrusted_app权限配置

查看当前Context

要看进程的Context,使用ps -Z

emu64xa:/ $ ps -AZ | grep google
u:r:hal_camera_default:s0      system         362     1   10891800   3272 0                   0 S android.hardware.camera.provider@2.7-service-google
u:r:permissioncontroller_app:s0:c179,c256,c512,c768 u0_a179 976 354 13918328 83660 0          0 S com.google.android.permissioncontroller
u:r:bluetooth:s0               bluetooth     1033   354   14050488  73628 0                   0 S com.google.android.bluetooth
u:r:priv_app:s0:c512,c768      u0_a167       1090   354   14016372 119796 0                   0 S com.google.android.apps.nexuslauncher
u:r:priv_app:s0:c512,c768      u0_a170       1157   354   13873728  68724 0                   0 S com.google.android.ext.services
u:r:untrusted_app_32:s0:c142,c256,c512,c768 u0_a142 1393 354 14070168 104520 0                0 S com.google.android.inputmethod.latin

查看文件的Context,使用

emu64xa:/ $ ls -Z
u:object_r:cgroup:s0                acct         u:object_r:tmpfs:s0                 debug_ramdisk    u:object_r:vendor_file:s0           odm                     u:object_r:sysfs:s0                 sys
u:object_r:apex_mnt_dir:s0          apex         u:object_r:device:s0                dev              u:object_r:vendor_file:s0           odm_dlkm                u:object_r:system_file:s0           system
u:object_r:rootfs:s0                bin          u:object_r:rootfs:s0                etc              u:object_r:oemfs:s0                 oem                     ?                                  
...

3. SeLinux的配置

参见https://android.googlesource.com/platform/system/sepolicy/

3.1 SeLinux文件体系

之前提到Android架构中大致包含AOSP厂商Vendor部分Android 8以上系统AOSP厂商供应商部分是独立配置方便OTA更新

这种架构SeLinux的Policy文件体系包含以下目录

system/sepolicy/public部分AOSP公开vender使用作为基础api比如声明domainattribute就在下面platform/system/sepolicy/public/attributes这部分Policy需要兼容处理因为Vender引用这里policy如果OTA单独升级AOSP需要向后兼容处理。详见https://source.android.com/docs/security/features/selinux/compatibility

system/sepolicy/privateAOSP内部使用system image内部policyvender不应该感知到这部分policy

system/sepolicy/vendorvender部分policy

device/manufacturer/device-name/sepolicy特定设备policy比如三星设备device/samsung/tuna/sepolicy

BoardConfig.mk makefile

AOSPSeLinux Policy文件一般不需要更改少量更改厂商主要修改定制Policy/device/manufacturer/device-name//device/manufacturer/device-name/BoardConfig.mk用于指定Policy文件具体路径通过BOARD_VENDOR_SEPOLICY_DIRS比如

device/samsung/tuna/BoardConfig.mk

BOARD_VENDOR_SEPOLICY_DIRS += device/samsung/tuna/sepolicy
system_ext  product分区

Android 11及以上系统system_ext  product分区独立单独policy并且区分publicprivatepublic部分同样vender引用system_extproduct版本兼容处理partner自己负责AOSP不负责

SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS:指定system_ext的public的目录,安装system_ext分区

SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS指定system_ext的private目录system_ext内部使用安装system_ext分区

PRODUCT_PUBLIC_SEPOLICY_DIRS指定product分区public目录安装product分区

PRODUCT_PRIVATE_SEPOLICY_DIRS指定product的private目录安装product分区

3.2 Policy文件

SeLinux策略配置相关文件统称Policy文件

Policy文件一般包含

TE文件

就是一堆.te文件TE定义Type访问规则进程文件Type定义、访问规则定制就只TE完成一般每个进程一个独立te文件所有文件te统一声明一个file.te文件详见3.3

Context files

file_contexts前面说过file_contexts里面定义文件context用于文件目录文件type关联起来

genfs_contexts用于文件系统(比如/proc和vfat)type关联起来

property_contexts用于Android系统propertiestype关联起来

service_contexts用于service进程type关联

seapp_contexts用于apptype关联

mac_permissions.xml根据appsignature包名app分配一个seinfoseinfo用于app没有明确关联一个type归属一个默认type

keystore2_key_contexts Keystore 2.0 namespaces分配一个label

Attribute

用来声明Attribute

security_classes

用来声明Class

3.3 TE(Type Enforcement)文件

所有的规则配置,或称Policy,都写在.te文件中。编写完TE文件后,将TE文件放在对应目录下,Android系统编译后.te文件将被编译成.cil文件。在init进程启动阶段,会将.cil文件汇总统一编译成一个命名为policy的文件。cil文件是可读的,policy文件是二进制的。在系统运行时最终加载使用的是policy文件。

policy文件一般在/sys/fs/selinux/policy

一般一个进程单独声明一个TE文件。比如一个dhcp进程单独有一个te文件叫dhcp.te。而文件的te统一整合在file.te(比如platform/system/sepolicy/public/file.te)中。

针对Platform(AOSP的部分)、Non-Platform(厂商、供应商的部分),TE会有不同的放置目录。

下面是TE文件的一个例子:

platform/system/sepolicy/public/dhcp.te

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

TE文件语法解析

type dhcp, domain; -- 声明一个type名为dhcp,其继承domain这个Attribute,也就是说在声明时便继承了domain所拥有的权限。domain属性是进程专用的,很显然这是一个进程的te文件。

permissive dhcp; -- 将dhcp标识为permissive模式。之前说到,SeLinux开启模式可以全局设置,也可以针对进程单独设置。这里是单独设置该进程的模式。

type dhcp_exec, exec_type, file_type; -- 声明一个type名为dhcp_exec, 从属于exec_type和file_type两个Attribute。也就是说同时继承两个Attribute所代表的文件。exec_type用于代表可执行文件,也就是进程的可执行文件入口;file_type代表通用文件。从这里我们知道dhcp_exec代表dhcp可执行文件的入口。

init_daemon_domain(dhcp) -- 这是一个宏,代表这是一个从init启动的进程,并且可以init通信。宏的源码见platform/system/sepolicy/public/te_macros

net_domain -- 也是一个宏,可以进行通用网络操作比如读写TCP操作socket

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service}; -- 这个就是具体规则描述dhcpsource selftargetcapability一个Class可以操作这句允许dhcp这个进程自己setgid操作self关键用来表示source可以自己什么操作

除了上面例子出现关键字有时我们看到typeattribute这个关键字代表之前已经声明Type关联一个之前声明Attribute

更多语法TypeStatements - SELinux Wiki

​​​​​​​4. SeLinux的编译

4.1 编译SeLinux Policy

Android 8以上编译过程/system  /vendorpolicy合并这个逻辑体现/platform/system/sepolicy/Android.mk

具体policy位置

Location

Contains

system/sepolicy/public

The platform's sepolicy API

system/sepolicy/private

Platform implementation details (vendors can ignore)

system/sepolicy/vendor

Policy and context files that vendors can use (vendors can ignore if desired)

BOARD_SEPOLICY_DIRS

Vendor sepolicy

BOARD_ODM_SEPOLICY_DIRS (Android 9 and higher)

Odm sepolicy

SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 and higher)

System_ext's sepolicy API

SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 and higher)

System_ext implementation details (vendors can ignore)

PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 and higher)

Product's sepolicy API

PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 and higher)

Product implementation details (vendors can ignore)

编译过程

  1. Policy转化成CIL( Common Intermediate Language )文件包括
    1. system + system_ext + productpublic部分policy
    2. 合并private + public policy
    3. 合并public + vendor and BOARD_SEPOLICY_DIRS policy
  2. public部分policy进行整理成对应版本policy作为vendor policy一部分然后publicpolicy合并public + vendor and BOARD_SEPOLICY_DIRS policy告知其哪部分可以连接到platformattribute
  3. 创建一个mapping文件连接platformvendor部分
  4. 合并所有policy文件整合mappingplatformvenderpolicy最终输出一个二进制的名为policy文件一般这个文件的位置在/sys/fs/sepolicy/policy。这个policy最终会被kernel加载。这个工作init进程初始化进行也就是运行时进行

4.2 预编译

SeLinux正式开启之前init进程收集所有cil文件将其编译policy这个过程需要花费1-2时间为了更快完成此过程会将CIL编一阶段预编译放在/vendor/etc/selinux/precompiled_sepolicy/odm/etc/selinux/precompiled_sepolicy并且附有sha256 摘要运行时检查sha256是否变化如果没有变化直接使用预编译文件

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

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

相关文章

计网--网络层个人笔记

网络层的IP分组由路由器转发&#xff0c;而每一个路由器有很多接口&#xff0c;那么从哪一个接口转发便需要转发表。 一、网络层基本功能 二、SDN基本概念 2.1 路由器 数据平面&#xff1a;转发的过程。一个分组如何从一个端口到达另一个端口。 控制平面&#xff1a;路由选择…

小程序渲染层图标错误

小程序渲染图标层出现错误&#xff1a; 官方提示&#xff1a;不影响可以忽略&#xff1b; 通过阿里巴巴矢量图标库--项目设置--字体格式--选中base64格式&#xff1b; 重新更新图标库代码&#xff0c;替换项目中的图标库&#xff1b; 重新加载小程序--渲染层错误的提示消失&…

基于vue+element+springboot+uniapp开发的智慧城管源码,java智慧城市管理综合执法系统源码

智慧城管源码&#xff0c;智慧执法&#xff0c;数字化城市管理综合执法系统源码 智慧城管系统充分利用物联网、云计算、信息融合、网络通讯、数据分析与挖掘等技术&#xff0c;对城市管理进行全方位覆盖。它通过建立城市综合管理平台&#xff0c;将城市的信息和管理资源有机结合…

TS + Vue3 elementUI 表格列表中如何方便的标识不同类型的内容,颜色区分 enum

TS Vue3 elementUI 表格列表中如何方便的标识不同类型的内容&#xff0c;颜色区分 enum 本文内容为 TypeScript 一、基础知识 在展示列表的时候&#xff0c;列表中的某个数据可能是一个类别&#xff0c;比如&#xff1a; enum EnumOrderStatus{"未受理" 1,"…

鸿蒙Harmony应用开发—ArkTS(@State装饰器:组件内状态)

State装饰的变量&#xff0c;或称为状态变量&#xff0c;一旦变量拥有了状态属性&#xff0c;就和自定义组件的渲染绑定起来。当状态改变时&#xff0c;UI会发生对应的渲染改变。 在状态变量相关装饰器中&#xff0c;State是最基础的&#xff0c;使变量拥有状态属性的装饰器&a…

分享ChatGPT超全面从基础到实战视频教程 - 带源码课件

分享ChatGPT超全面从基础到实战视频教程 - 带源码课件。本课程从ChatGPT的注册和使用讲起&#xff0c;分析了主流ChatGPT的应用场景&#xff0c;针对代码类开发场景做了详细实践&#xff0c;通过ChatGPT完成实战项目&#xff0c;从0-1搭建聊天机器人&#xff0c;轻松学习ChaGPT…

【mysql 127错误】mysql启动报错mysqld.service: Failed with result ‘exit-code‘.

无网环境&#xff0c;mysql 安装 出现如下错误 [rootmysql tools]# systemctl status mysqld.service ● mysqld.service - MySQL ServerLoaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)Active: failed (Result: exit-code) since…

基于OpenCV的图像处理案例之图像矫正(Python)

Index 目录索引 写在前面解决思路参考 写在前面 本文通过一个案例介绍如何使用OpenCV将倾斜的扫描文档图像进行水平矫正。 解决思路 因为扫描图像中的大部分文字倾斜后&#xff0c;同一行文字也在同一条直线&#xff0c;所以可以通过拟合直线来计算文本倾斜角度&#xff0c;…

ETL的全量和增量模式

在当今信息爆炸的时代&#xff0c;数据管理已经成为各行各业必不可少的一环。而在数据管理中&#xff0c;全量与增量模式作为两种主要的策略&#xff0c;各自具有独特的优势和适用场景&#xff0c;巧妙地灵活运用二者不仅能提升数据处理效率&#xff0c;更能保障数据的准确性。…

没有磁盘整列下的多机分布式存储:使用rysnc+多服务器文件/文件夹内容同步

目录 0.为什么要定时同步 1.程序安装 2.文件夹设置rsync使用 3.使用cron进行定时任务 0.为什么要定时同步 作为科研党&#xff0c;实验室有多个服务器&#xff0c;但是都是分批买的没有上磁盘整列&#xff0c;所以一个服务器上跑的东西并不能同步&#xff0c;有时候挂任务要…

docker基础(八)之docker commit,docker tag,docker cp,docker diff

文章目录 概述docker commit语法OPTIONS说明&#xff1a;docker commit --help实例使用场景 docker tag语法示例使用场景为什么要这样做呢&#xff1f; docker cp语法OPTIONS说明&#xff1a;docker cp --help示例 docker diff语法示例使用场景&#xff1a; 概述 用于学习和记…

贪心算法入门

简介 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。也就是首先选取局部最优&#xff0c;从局部最优推出全局最优。 举例…

隐语笔记3 —— 隐语架构

隐语架构一览 隐语产品层 定位&#xff1a; 通过可视化产品&#xff0c;降低终端用户的体验和演示成本。通过模块化API降低技术集成商的研发成本。 人群画像&#xff1a; 隐私保护计算集成商&#xff0c;产品人员&#xff0c;隐私保护计算需求方&#xff0c;开发人员&#xff…

IDEA | 资源文件中文乱码问题解决

问题 IDEA打开资源文件&#xff0c;显示乱码问题。 解决方案 1、电脑是mac&#xff0c;点击IDEA->【Preferences】->【Editor】->【File Encodings】 2、选择【Properties Files】中的UTF-8&#xff0c;并勾选Transparent native-to-ascii conversion。 3、最后点击…

罗格朗逸景PLUS IOT智能系统发布,为您提供更智能的生活体验!

罗格朗全新推出的逸景PLUS IOT智能系统现已正式上市,采用纤薄纯平的设计,功能丰富全面,支持灯光/温度/场景控制、背景音乐等多种功能,整合罗格朗IOT2.0系统,集成可视对讲,为用户打造更舒适、安全的智能生活。 罗格朗智能家居 罗格朗是全球电气与智能建筑系统专家,创立于1865年…

QT tableWidget横向纵向设置

横向控件 要设置QTabWidget选项卡的字体方向&#xff0c;可以使用QTabWidget的setTabPosition()方法。通过传递Qt枚举值QTabWidget.east或QTabWidget.west作为参数&#xff0c;可以设置选项卡的字体方向为从左到右或从右到左。 myTabWidget QTabWidget() myTabWidget.setTabP…

基于python+vue的O2O生鲜食品订购flask-django-nodejs-php

近年来互联网络的迅猛发展和电子终端设备的普及&#xff0c;赋予了各行业充足的发展空间。微信小程序的O2O生鲜食品订购相比于传统信息技术&#xff0c;时效性是它最大的特色&#xff0c;已经在电子娱乐、经济等中发挥着举足轻重的作用。短时间内迅速扩大了线上管理系统的规模。…

牛,The O-one ——通过语音交互控制电脑的开源语言模型

模型介绍 The O-one &#xff1a;一个创新的开源语言模型计算机 可以让你通过语音交互来和你的计算机进行对话&#xff0c;完成询问、指令下达等任务。灵感居然来自Andrej Karpathy 的 LLM 操作系统。O1运行一个代码解释语言模型&#xff0c;并在计算机内核发生特定事件时调用…

机器学习——线性回归(头歌实训)

头歌机器学习实训代码、答案&#xff0c;如果能够帮到您&#xff0c;希望可以点个赞&#xff01;&#xff01;&#xff01; 如果有问题可以csdn私聊或评论&#xff01;&#xff01;&#xff01;感谢您的支持 目录 第1关&#xff1a;简单线性回归与多元线性回归 第2关&#…

【机器学习入门 】支持向量机

系列文章目录 第1章 专家系统 第2章 决策树 第3章 神经元和感知机 识别手写数字——感知机 第4章 线性回归 第5章 逻辑斯蒂回归和分类 前言 支持向量机(Support Vector Machine) 于1995年发表&#xff0c;由于其优越的性能和广泛的适用性&#xff0c;成为机器学习的主流技术&…