Centos7.8如何设置系统文本模式启动

小白菜 回复了问题 2 人关注 1 个回复 24 次浏览 4 天前 来自相关话题

kvm虚拟机启动报错Unable to find security driver for model selinux

OS小编 发表了文章 0 个评论 64 次浏览 2022-05-17 15:46 来自相关话题

好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误: [root@kvm-labs kvm]# virsh start centos7-lab ...查看全部

好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误:


[root@kvm-labs kvm]# virsh start centos7-lab-node1
error: Failed to start domain centos7-lab-node1
error: unsupported configuration: Unable to find security driver for model selinux

根据错误提示,怀疑是系统selinux的问题,但是发现selinux是disabled,难道要强制用selinux,不合理啊。重新梳理逻辑,kvm虚拟机是可被定义的,是不是定义的配置文件中有selinux相关定义,那是不是可以去掉,经过实验还真ok,解决步骤如下。


1. 进入虚拟机配置文件目录

cd /etc/libvirt/qemu/
# 如果你构建环境修改过默认路径,根据实际情况进入

2. 编辑虚拟机配置文件

vim  centos7-lab-node1.xml

.....................
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</rng>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'/>
</domain>

如上,删除<seclabel type='dynamic' model='selinux' relabel='yes'/> , 然后保存退出。


3. 重新定义配置文件

virsh define ./centos7-lab-node1.xml

然后重新执行virsh start centos7-lab-node1 就可以了。


如果想迁移虚拟机的存储路径也可以关机,修改配置文件下的存储路径,并将.qcow2文件移动到相应的目录下即可.


<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/data/kvmdata/centos7-lab-node1.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>

修改完成后,然后重新定义配置文件,重启虚拟机即可。

Centos系统进入单用户修改root用户密码

OS小编 发表了文章 0 个评论 59 次浏览 2022-05-16 17:15 来自相关话题

1. 重启系统,在选择进入系统界面按字母e2. 在r ...查看全部

1. 重启系统,在选择进入系统界面按字母e

2. 在rhgb前添加’rw’ ,在行末添加 ‘init=/bin/sh’ ,按 ‘Ctrl+x’ 进入系统

进入系统后,修改密码

echo "www.baidu.com | passwd --stdin root
touch /.autorelabel
exec /sbin/init

等待一会,点击回车,进入重启。

网页内容不允许复制怎么办?

空心菜 回复了问题 2 人关注 1 个回复 121 次浏览 2022-04-24 17:15 来自相关话题

安可产业名录和国产化替代

chris 发表了文章 0 个评论 4193 次浏览 2021-11-30 15:52 来自相关话题

关于国家信息化安全可靠工程随着信息安全问题日益突出,信息安全已上升至国家战略,自主可控,国产化替代已成为历史趋势。2019年开始我国信息、网安领域企业逐渐发力“安全可靠工程”,安全可靠工程战略意义在于证明我国具有安全可靠关键系统、关键应 ...查看全部

关于国家信息化安全可靠工程

随着信息安全问题日益突出,信息安全已上升至国家战略,自主可控,国产化替代已成为历史趋势。2019年开始我国信息、网安领域企业逐渐发力“安全可靠工程”,安全可靠工程战略意义在于证明我国具有安全可靠关键系统、关键应用及关键软硬件产品的研发集成能力,能够初步实现对国外信息技术产品的全方位替代,在新的历史起点上构建起网络安全的“铜墙铁壁”。在党政办公及国家重要信息系统推进国产化替代,实现安全可靠、自主可控,保障国家信息安全的工作已全面展开。

安可名录

安全可靠技术和产业联盟主要成员单位包括联盟理事和联盟会员两大类。
其中联盟理事(19家)又分为:集成厂商(10家)、测试厂商(4家)、互联网厂商(3家)和高等院校(2家)四大类。

集成厂商(10家)包括:
华宇软件、神州航天软件、东华软件、东软集团、航天信息、浪潮软件集团、神州信息、太极股份、同方股份、中国软件

测试机构(4家)包括:
国家工业信息安全发展研究中心、中国电子技术标准化研究院、工业和信息化部电子第五研究所、中国电子信息产业发展研究院

互联网厂商(3家)包括:
阿里云、金山软件、华为技术

高等院校(2家)包括:
北京航空航天大学、北京理工大学

联盟会员则包含:芯片厂商(7家)、集成厂商(12家)、整机厂商(8家)、操作系统厂商(9家)、数据库厂商(6家)、中间件厂商(3家)、流版签厂商(7家)、外设固件厂商(3家)、安全厂商(6家)、网络厂商(3家)、互联网厂商(2家)、存储厂商(5家)和应用软件厂商(2家)共十二大类。


芯片厂商(7家)包括:
上海兆芯(X86)、东土军悦(交换机芯片、东土科技)、国科微(安防、存储、物联网芯片)、盛科网络(交换机芯片、中国电子、振华科技)、天津飞腾(ARM、中国长城、振华科技)、上海高性能集成电路设计中心(Alpha、申威)、龙芯中科(MIPS)

集成厂商(12家)包括:
百得科技、华胜天成、中软信息(中国软件)、广东省信息工程公司、中科软、南威软件、太极信息(太极股份)、烽火信息(烽火通信)、万达信息、中软系统(中国软件)、中科九洲、长城软件(中国软件)

整机厂商(8家)包括:
上海仪电智通、联想长风、华胜天成、长城科技(中国长城)、宝德网络、曙光信息(中科曙光)、百信信息、北京计算机技术及应用研究所(航天二院706所)

操作系统厂商(9家)包括:
中科方德(兆芯)、一铭软件、湖南麒麟信安(中国软件)、天津麒麟(中国软件)、思普投资(X86)、深之度、普华基础软件(中国电科)、航天国盛(航天科技)、中标软件(中国软件)

数据库厂商(6家)包括:
武汉达梦(中国软件)、神舟通用(航天科技)、人大金仓(太极股份)、南大通用、恒辉信达、瀚高基础软件

中间件厂商(3家)包括:
金蝶天燕中间件、东方通、中创软件

流版签厂商(7家)包括:
金格科技(电子签章)、方正国际软件(电子文档)、书生电子(启明星辰、安全文档)、数科网维(版式OFD)、航天福昕(文档OFD)、安证通(电子签章)、永中软件(office,办公软件)

外设固件厂商(3家)包括:
立思辰(文件管理)、中电科技(中国电子、BIOS等)、光电通信(传真机)

安全厂商(6家)包括:
星网锐捷(通信、安全)、中孚信息(安全保密)、安宁创新(邮件、消息)、中安网脉(密码、存储)、海泰方圆(密码、安全)、卫士通(密码、芯片、系统)

网络厂商(3家)包括:
紫光集团(从芯到云)、迈普通信(中国电子、网络设备)、仰联信通(交换机)

互联网厂商(2家)包括:
拓尔思、恒生电子

存储厂商(5家)包括:
滕凌科技(存储)、亚细亚智业(存储灾备)、同有科技(存储)、鲸鲨软件(存储)、鼎甲科技(中国电子、灾备)

应用软件厂商(2家)包括:
慧点科技(太极股份、管理软件)、华电园技术(办公自动化)

国产化软硬件资源

应用软件
监控国产数据库:达梦数据库、南大通用、人大金仓、神舟通用;

大数据产业下,对金融、电信、航空、制造等行业影响非常明显,其中国产数据库的作用被不断提升,担负起捍卫国家信息安全和技术的重任。
监控国产中间件:东方通、中创、金碟等中间件;

中间件一直是基础软硬件发展中不可缺少的一环,占居重要的地位。2018年以来本土中间件加快进入电信、金融、政府等行业,由东方通作为开拓者和领导者,中创、宝兰德等追其后。


操作系统
监控中标麒麟、银河麒麟、深度科技、红旗、中兴新支点等操作系统;

在持续的贸易战背景下,由于我们受到了外国的管控,操作系统等核心技术一度面临被限制使用的局面,于是国产操作系统被推到了风口浪尖。


硬件资源
监控国产服务器:华为、曙光、H3C、联想、浪潮;
国产服务器发展已将近二十载,二十载潮起潮落,国产服务器已涌现出联想、曙光、浪潮、华为等一批民族品牌。现在国产服务器已抢占更多服务器市场份额。

监控国产存储设备:华为、曙光、H3C、同有、浪潮;


网络资源
监控国产网络设备:华为、H3C、仰联、TP-LINK、ZTE中兴、锐捷等;

监控国产安全设备:天融信、启明星辰、绿盟、网康、趋势科技、山石网科等;
中国最核心的网络安全设备大部分依赖于进口,不具有强大的防御与反击能力,安全问题依然严峻。单靠技术无法抑制网络安全事件增长。核心网络设备国产化是解决这一问题最好的办法。



应用环境
兼容国产数据库:达梦数据库、南大通用、人大金仓、神舟通用;

兼容国产中间件:东方通、中创、金碟等中间件;


硬件环境


兼容国产服务器:华为、曙光、H3C、联想、浪潮;
兼容国产 CPU:龙芯、飞腾、海思、鲲鹏、展讯通信;

系统环境
兼容国产操作系统:中标麒麟、银河麒麟、深度科技、红旗、中兴新支点;

漏洞风险评估CVSS介绍

koyo 发表了文章 0 个评论 817 次浏览 2021-11-06 17:29 来自相关话题

什么是CVSS通用弱点评价体系(CVSS)是由NIAC开发、FIRST维护的一个开放并且能够被产品厂商免费采用的标准。利用该标准,可以对弱点进行评分,进而帮助我们判断修复不同弱点的优先等级。 C ...查看全部

什么是CVSS

通用弱点评价体系(CVSS)是由NIAC开发、FIRST维护的一个开放并且能够被产品厂商免费采用的标准。利用该标准,可以对弱点进行评分,进而帮助我们判断修复不同弱点的优先等级。


CVSS(Common Vulnerability Scoring System),即”通用漏洞评分系统”,是一个”行业公开标准,其被设计用来评测漏洞的严重程度,并帮助确定所需反应的紧急度和重要度”。


它的主要目的是帮助人们建立衡量漏洞严重程度的标准,使得人们可以比较漏洞的严重程度,从而确定处理它们的优先级。CVSS得分基于一系列维度上的测量结果,这些测量维度被称为量度(Metrics)。漏洞的最终得分最大为10,最小为0。


得分7~10的漏洞通常被认为比较严重,得分在4~6.9之间的是中级漏洞,0~3.9的则是低级漏洞。


CVSS系统包括三种类型的分数:基本分数、暂时分和环境分。


基本得分临时得分通常由安全产品卖主、供应商给出,因为他们能够更加清楚的了解漏洞的详细信息;


环境得分通常由用户给出,因为他们能够在自己的使用环境下更好的评价该漏洞存在的潜在影响。


所以应该是基于漏洞库的扫描, 需要预先知道该漏洞的威胁值?


就是说漏洞应该预先有脆弱性等级,系统的安全性评估是综合各个漏洞来进行的?


CVSS 2.0 计算方法: 通用漏洞评估方法CVSS 3.0 计算公式及说明 - caya - 博客园 (cnblogs.com)


一些指标具有不确定性和复杂性,会导致完全的定量分析困难。3个客观性指标和11个主观性指标。下一步:指标量化(客观性指标量化和主观性指标量化)。


CVSS评分计算方法

A. 基本评价(Base Metric)

基本评价指的是该漏洞本身固有的一些特点及这些特点可能造成的影响的评价分值


































序号 要素 可选值 评分
1 攻击途径 (AccessVector) 本地/远程 0.7/1.0
2 攻击复杂度(AccessComplexity) 高/中/低 0.6/0.8/1.0
3 认证(Authentication) 需要/不需要 0.6/1.0
4 机密性(Conflmpact) 不受影响/部分/完全 0/0.7/1
5 完整性(integlmpact) 不受影响/部分/完全 0/0.7/1
6 可用性(Availlmpact) 不受影响/部分/完全 0/0.7/1
7 权值倾向 平均/机密性/完整性/可用性 各0.333/权值倾向要素0.5另两个0.25

基础评价 = 四舍五入(10 * 攻击途径 攻击复杂度 认证 ((机密性 机密性权重) + (完整性 完整性权重) + (可用性 可用性权重)))


B.生命周期评价(Temporal Metric)

是针对最新类型漏洞(如: 0day漏洞)设置的评分项,因此SQL注入漏洞不用考虑


因此这里也列举出三个与时间紧密关联的要素如下:


















序号 要素 可选值 评分
1 可利用性 未证明/概念证明/功能性/完全代码 0.85/0.9/0.95/1.0
2 修复措施 官方补丁/临时补丁/临时解决方案/无 0.87/0.90/0.95/1.0
3 确认程度 不确认/未经确认/已确认 0.9/0.95/1.0

生命周期评价 =四舍五入(基础评价 可利用性 修复措施 * 未经确认)


C.环境评价(Environmental Metric)

每个漏洞会造成的影响大小都与用户自身的实际环境密不可分,因此可选项中也包括了环境评价,这可以由用户自评。(用户扫描配置时填写)














序号 要素 可选值 评分
1 危害影响程度 无/低/中/高 0/0.1/0.3/0.5
2 目标分布范围 无/低/中/高(0/1-15%/16-49%/50-100%) 0/0.25/0.75/1.0

环境评价 = 四舍五入<(生命周期评价 + [(10 -生命周期评价) *危害影响程度]) *目标分布范围>


评分与危险等级













序号 评分 危险等级
1 [0,4]
2 [4,7]
3 [7,10]

Mac pro怎么安装brew

空心菜 回复了问题 2 人关注 2 个回复 3429 次浏览 2021-07-21 19:32 来自相关话题

yum和apt-get命令对比

星物种 发表了文章 0 个评论 951 次浏览 2021-06-17 14:21 来自相关话题

说明 Redhat系 ...查看全部






















































说明 Redhat Debian
更新缓存 yum makecache apt-get update
更新包 yum update apt-get upgrade
检索包 yum search apt-cache search
检索包内文件 yum provides apt-file search
安装指定的包 yum install apt-get install
删除指定的包 yum remove apt-get remove
显示指定包的信息 yum info apt-cache show
显示包所在组的一览 yum grouplist -
显示指定包所在组的信息 yum groupinfo -
安装指定的包组 yum groupinstall -
删除指定的包组 yum groupremove -
参考库的设定文件 /etc/yum.repos.d/* /etc/apt/sources.list
安装完的包的列表 rpm -qa dpkg-query -l
显示安装完的指定包的信息 rpm -qi apt-cache show
安装完的指定包内的文件列表 rpm -ql dpkg-query -L
安装完的包的信赖包的列表 rpm -qR apt-cache depends
安装完的文件信赖的包 rpm -qf dpkg -S

什么是CICD

OS小编 发表了文章 0 个评论 1097 次浏览 2021-05-15 15:27 来自相关话题

传统的应用发布模式如果你经历体验过传统的应用发布,你可能就 ...查看全部

传统的应用发布模式


如果你经历体验过传统的应用发布,你可能就会觉得CICD有足够吸引你的地方,反之亦然。一般一个研发体系中都会存在多个角色:开发、测试、运维。当时我们的应用发布模式可以能是这样的:

  • 开发团队在开发环境中完成软件开发,单元测试,测试通过,提交到代码版本管理库;
  • 开发同学通知运维同学项目可以发布了,然后运维同学下载代码进行打包和构建,生成应用制品;
  • 运维同学使用部署脚本将生成的制品部署到测试环境,并提示测试同学可以进行产品的测试;
  • 测试同学开始进行手动、自动化测试,测试完成后提醒运维同学可以进行预生产环境部署;
  • 运维同学开始进行预生产环境部署,然后测试同学进行测试,测试完成后,开始部署生产环境。

当然我描述的可能只是其中的一部分,手动操作很多、出现的问题很多。上面看似很流畅的过程,其实每次构建或发布都可能会出现问题。未对每次提交验证、构建环境不一致:开发人员本地测试成功后提交代码,运维同学下载代码进行编译却出现了错误。


存在的问题:


  1. 错误发现不及时: 很多错误在项目的早期可能就存在,到最后集成的时候才发现问题;
  2. 人工低级错误发生: 产品和服务交付中的关键活动全都需要手动操作;
  3. 团队工作效率低: 需要等待他人的工作完成后才能进行自己的工作;
  4. 开发运维对立: 开发人员想要快速更新,运维人员追求稳定,各自的针对的方向不同。

经过上述问题我们需要作出改变,如何改变?


什么是CICD


软件开发的连续方法基于自动执行脚本,以最大程度地减少在开发应用程序时引入错误的机会。从开发新代码到部署新代码,他们几乎不需要人工干预,甚至根本不需要干预。

它涉及到在每次小的迭代中就不断地构建,测试和部署代码更改,从而减少了基于错误或失败的先前版本开发新代码的机会。


此方法有三种主要方法,每种方法都将根据最适合您的策略的方式进行应用。


持续集成 CI(Continuous Integration)


在传统软件开发过程中,集成通常发生在每个人都完成了各自的工作之后。在项目尾声阶段,通常集成还要痛苦的花费数周或者数月的时间来完成。持续集成是一个将集成提前至开发周期的早期阶段的实践方式,让构建、测试和集成代码更经常反复地发生。

开发人员通常使用一种叫做CI Server的工具来做构建和集成。持续集成要求史蒂夫和安妮能够自测代码。分别测试各自代码来保证它能够正常工作,这些测试通常被称为单元测试(Unit tests)。


代码集成以后,当所有的单元测试通过,史蒂夫和安妮就得到了一个绿色构建(Green Build)。这表明他们已经成功地集成在一起,代码正按照测试预期地在工作。然而,尽管集成代码能够成功地一起工作了,它仍未为生产做好准备,因为它没有在类似生产的环境中测试和工作。


CI是需要对开发人员每次的代码提交进行构建测试验证。确定每次提交的代码都是可以正常编译测试通过的。在没有持续集成服务器的时候,我们可以写一个程序来监听版本控制系统的状态,当出现了push动作则触发相应的脚本运行编译构建等步骤。现在有了专业的持续集成服务器后,我们借助持续集成服务器来实现版本控制系统中代码提交触发构建测试等验证步骤。


持续合并开发人员正在开发编写的所有代码的一种做法。通常一天内进行多次合并和提交代码,从存储库或生产环境中进行构建和自动化测试,以确保没有集成问题并及早发现任何问题。


开发人员提交代码的时候一般先在本地测试验证,只要开发人员提交代码到版本控制系统就会触发一条提交流水线,对本次提交进行验证。


持续交付 CD (Continuous Delivery)


Continuous Delivery (CD) 持续交付是持续集成的延伸,将集成后的代码部署到类生产环境,确保可以以可持续的方式快速向客户发布新的更改。如果代码没有问题,可以继续手工部署到生产环境中。

持续交付CD:是基于持续集成的基础上,将集成后的代码自动化的发布到各个环境中测试(DEV TEST UAT STAG),确定可以发布生产版本。这里我们可以借用制品库实现制品的管理,根据环境类型创建对应的制品库。一次构建,到处运行


  • 开发环境发布:我们可以将开发环境产出的制品部署进行测试,没有问题后上传到测试环境的制品库中。
  • 测试环境发布:此时通知测试人员可以进行测试环境发布测试,获取测试环境制品库中的制品,发布到测试环境验证。验证通过将制品上传到预生产环境制品库。
  • 预生产环境发布:获取预生产环境制品,进行部署测试。测试成功后可以将制品上传到生产库中。
  • 手动部署生产环境。

持续交付是超越持续集成的一步。不仅会在推送到代码库的每次代码更改时都进行构建和测试,而且,作为附加步骤,即使部署是手动触发的,它也可以连续部署。此方法可确保自动检查代码,但需要人工干预才能从策略上手动触发更改的部署。


持续部署 CD(Continuous Deploy)


如果真的想获得持续交付的好处,应该尽早部署到生产环境,以确保可以小批次发布,在发生问题时可以轻松排除故障。于是有了持续部署。

通常可以通过将更改自动推送到发布系统来随时将软件发布到生产环境中。持续部署 会更进一步,并自动将更改推送到生产中。类似于持续交付,持续部署也是超越持续集成的进一步。不同之处在于,您无需将其手动部署,而是将其设置为自动部署。部署您的应用程序完全不需要人工干预。


持续部署CD:是基于持续交付的基础上,将在各个环境经过测试的应用自动化部署到生产环境。其实各个环境的发布过程都是一样的。应用发布到生产环境后,我们需要对应用进行健康检查、添加应用的监控项、 应用日志管理。


我们通常将这个在不同环境发布和测试的过程叫做部署流水线, 持续部署是在持续交付的基础上,把部署到生产环境的过程自动化。


参考:



https://blog.csdn.net/weixin_40046357/article/details/107478696


http://www.idevops.site/gitlabci/chapter01/01/


https://www.jianshu.com/p/654505d42180


了解共享库动态加载

OS小编 发表了文章 1 个评论 937 次浏览 2021-04-30 15:59 来自相关话题

在本文中,我将尝试解释在Linux系统中动态加载共享库的内部工作原理。 这边文章不是一个如何引导,尽管它确实展示了如何编译和调试共享库和可执行文件。为了解动态加载的内部工作方式进行了优化。写这篇文章是为了消除我在该主题上的知识欠 ...查看全部

在本文中,我将尝试解释在Linux系统中动态加载共享库的内部工作原理。


这边文章不是一个如何引导,尽管它确实展示了如何编译和调试共享库和可执行文件。为了解动态加载的内部工作方式进行了优化。写这篇文章是为了消除我在该主题上的知识欠缺,以便成为一名更好的程序员。我希望它也能帮助您变得更好。


什么是共享库

库是一个包含编译后的代码和数据的文件。一般来说,库非常有用,因为它们可以缩短编译时间(在编译应用程序时不必编译依赖关系的所有源代码)和模块化开发过程。


静态库链接到已编译的可执行文件(或另一个库)中。编译后,新组件将包含静态库的内容。


共享库在运行时由可执行文件(或其他共享库)加载。这让它们变得更加复杂,通常大家对这个领域可能存在认知障碍,我们将在这篇文章中讨论。


示例设置

为了探索共享库的世界,我们将在本文中使用一个示例。我们将从三个源文件开始:


main.cpp是我们定义的可执行文件的主文件, 它不会做太多, 只是从我们将要编译的随机库random调用一个函数:


$ vi main.cpp

#include "random.h"

int main() {
return get_random_number();
}

头文件random.h将定义一个简单的函数:


$ vi random.h

int get_random_number();

它将在其源文件中提供一个简单的实现, random.cpp


$ vi random.cpp

#include "random.h"

int get_random_number(void) {
return 4;
}

Note: 所有示例均在Ubuntu 14.04系统上运行



编译共享库

在编译实际库之前,我们将从random.cpp创建一个目标文件:


$ clang++ -o random.o -c random.cpp

通常,一切正常后,构建工具不会打印到标准输出。以下是所有解释的参数:


  • -o random.o: 将输出文件名定义为random.
  • -c: 不尝试任何链接(只编译)
  • random.cpp: 输入文件

接下来,我们将目标文件编译到共享库中:


$ clang++ -shared -o librandom.so random.o

参数-shared用于指定应该构建共享库的标志。



注意: librandom.so称为共享库。这不是随心所欲的, 呗调用的共享库应该以lib<name>.so使它们以后正确链接(如我们在下面的链接部分中所见)。



编译和链接动态可执行文件

首先,我们将为main.cpp创建一个共享对象:


$ clang++ -o main.o -c main.cpp

与之前完全相同random.o


现在,我们将尝试创建一个可执行文件:


$ clang++ -o main main.o
main.o: In function `main':
main.cpp:(.text+0x10): undefined reference to `get_random_number()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

好吧,看来我们需要告诉clang我们要使用librandom.so:


$ clang++ -o main main.o -lrandom
/usr/bin/ld: cannot find -lrandom
clang: error: linker command failed with exit code 1 (use -v to see invocation)

注意: 我们选择动态链接librandom.so到main。可以静态地执行此操作-并将random库中的所有符号直接加载到main可执行文件中。



我们告诉编译器我们要使用librandom文件。由于它是动态加载的,为什么我们在编译时需要它?好吧,原因是我们需要确保依赖的库包含可执行文件所需的所有符号。还要注意,我们指定random的是库的名称,而不是librandom.so。还记得关于库文件命名的约定吗?这是使用它的地方。


因此,我们需要让我们clang知道在哪里搜索共享库。我们用-L参数来做到这一点。请注意,由指定的路径-L仅在链接时影响搜索路径,而不会在运行时影响。我们将指定当前目录:


$ clang++ -o main main.o -lrandom -L.

现在它可以运行了,但是:


$ ./main 
./main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

当找不到依赖项时,这是我们得到的错误。这将在我们的应用程序甚至运行一行代码之前发生,因为共享库是在可执行文件中的符号之前加载的。


到这就需要面对如下几个问题:


  1. main它怎么知道依赖librandom.so?
  2. main在哪里查找librandom.so?
  3. 要这么告诉main在当前目录查找librandom.so?

要回答这些问题,我们将不得不更深入地研究这些文件的结构。


ELF - 可执行和可链接的格式

共享库和可执行文件格式称为ELF(可执行和可链接格式)。如果您查看Wikipedia文章,您会发现它是一团糟,因此我们不会一一列举。总之,ELF文件包含:


  • ELF Header
  • 文件数据,可能包含:
    1. 程序头表(段头列表)
    2. 段头表(列表章节标题)
    3. 以上两个标题指向的数据

ELF标头指定程序标头表中段的大小和数量,以及节标头表中段的大小和数量。每个这样的表都由固定大小的条目组成(我使用该条目在适当的表中描述段标题或节标题)。条目是标题,并且包含指向该段或节的实际主体位置的指针(文件中的偏移量)。该主体存在于文件的数据部分中。更复杂的是-每个部分都是一个段的一部分,一个段可以包含许多段。


实际上,相同的数据要么作为段的一部分引用,要么作为段的一部分引用,这取决于当前上下文。链接时使用分段,执行时使用分段。

我们将使用readelf命令读取ELF。让我们从查看以下内容的ELF标头开始分析main


$ readelf -h main
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4005e0
Start of program headers: 64 (bytes into file)
Start of section headers: 4584 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 27

我们可以看到,这是Unix上的ELF文件(64位), 其类型为EXEC,这是一个可执行文件-符合预期。它有9个程序标头(意味着有9个segment)和30个节标头(即section)。


下一步-程序头(program headers):


$ readelf -l main

Elf file type is EXEC (Executable file)
Entry point 0x4005e0
There are 9 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000089c 0x000000000000089c R E 200000
LOAD 0x0000000000000dd0 0x0000000000600dd0 0x0000000000600dd0
0x0000000000000270 0x0000000000000278 RW 200000
DYNAMIC 0x0000000000000de8 0x0000000000600de8 0x0000000000600de8
0x0000000000000210 0x0000000000000210 RW 8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x0000000000000774 0x0000000000400774 0x0000000000400774
0x0000000000000034 0x0000000000000034 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000dd0 0x0000000000600dd0 0x0000000000600dd0
0x0000000000000230 0x0000000000000230 R 1

Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got

同样,我们看到我们有9个程序标头。它们的类型LOAD(有2个),DYNAMIC,NOTE等等。我们也可以看到各段的部分所有权。


最后-节标题(section headers):


$ readelf -S main
There are 30 section headers, starting at offset 0x11e8:

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4

[..]

[21] .dynamic DYNAMIC 0000000000600de8 00000de8
0000000000000210 0000000000000010 WA 6 0 8

[..]

[28] .symtab SYMTAB 0000000000000000 00001968
0000000000000618 0000000000000018 29 45 8
[29] .strtab STRTAB 0000000000000000 00001f80
000000000000023d 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

为了简洁起见,我对此进行了修剪。我们看到列出的30个部分带有各种名称(例如.note.ABI-tag)和类型(例如SYMTAB)。


您现在可能会感到困惑, 不用担心一般不会考这方面的东西。在他们的:因为我们感兴趣的是这个文件的特定部分,我解释这个程序头表,ELF文件可以有(和共享特别库必须具有)段头一个描述段型的PT_DYNAMIC。该部分拥有一个名为的部分.dynamic,其中包含有用的信息以了解动态依赖性。


直接依赖

我们可以使用readelf实用工具来进一步探索.dynamic可执行文件的部分。


特别是,本节包含我们ELF文件的所有动态依赖项。我们仅将其指定librandom.so为依赖项,因此我们希望列出main的依赖项:


$ readelf -d main | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [librandom.so]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]

objdump可执行文件可以提供类似的结果。在这种情况下,例如:objdump -p librandom.so | grep NEEDED将打印非常相似的输出。



我们可以看到librandom.so我们指定的,但是我们还得到了四个我们没有想到的额外依赖项。这些依赖性似乎出现在所有已编译的共享库中。这些是什么呢?


  • libstdc++: 标准C++库
  • libm: 包含基本数学函数的库
  • libgcc_s: GCC(GNU编译器集合)运行时库
  • libc: C库:它定义了系统调用和其他基础设施如库open,malloc,printf,exit等。

好的, 我们已经知道main依赖于librandom.so, 那么,为什么在运行时main找不到librandom.so


运行时搜索路径

ldd是一个工具,使我们可以查看递归共享库的依赖关系。这意味着我们可以看到程序在运行时需要的所有共享库的完整列表。这也让我们看到了在那里这些依赖所在。让我们继续运行main,看看会发生什么:


$ ldd main
linux-vdso.so.1 => (0x00007fff889bd000)
librandom.so => not found
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f07c55c5000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f07c52bf000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f07c50a9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f07c4ce4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f07c58c9000)

如上,我们看到了文件librandom.so依赖的动态链接库文件,但是提示是not found


我们还可以看到,我们还有两个附加的库(vdsold-linux-x86-64)。它们是间接依赖关系, 更重要的是,我们看到ldd报告了库的位置。比如libstdc++ldd报告其位置为/usr/lib/x86_64-linux-gnu/libstdc++.so.6, 这是怎么知道的呢?


我们的依赖项中的每个共享库都按顺序在以下位置进行搜索:


  1. 可执行文件rpath中列出的目录;
  2. LD_LIBRARY_PATH环境变量中的目录,该变量包含以冒号分隔的目录列表(例如:/path/to/libdir:/another/path);
  3. 可执行文件runpath中列出的目录;
  4. 文件/etc/ld.so.conf中包含的文件目录列表;
  5. 默认系统库-通常为/lib/usr/lib (设置-z nodefaultlib参数编译时可跳过)

修复我们的可执行文件

好的, 我们验证了librandom.so是列出的依赖项,但找不到。我们知道在哪里搜索依赖项,ldd再次使用以下命令,确保目录实际上不在搜索路径中:


$ LD_DEBUG=libs ldd main
[..]

3650: find library=librandom.so [0]; searching
3650: search cache=/etc/ld.so.cache
3650: search path=/lib/x86_64-linux-gnu/tls/x86_64:/lib/x86_64-linux-gnu/tls:/lib/x86_64-linux-gnu/x86_64:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/tls/x86_64:/usr/lib/x86_64-linux-gnu/tls:/usr/lib/x86_64-linux-gnu/x86_64:/usr/lib/x86_64-linux-gnu:/lib/tls/x86_64:/lib/tls:/lib/x86_64:/lib:/usr/lib/tls/x86_64:/usr/lib/tls:/usr/lib/x86_64:/usr/lib (system search path)
3650: trying file=/lib/x86_64-linux-gnu/tls/x86_64/librandom.so
3650: trying file=/lib/x86_64-linux-gnu/tls/librandom.so
3650: trying file=/lib/x86_64-linux-gnu/x86_64/librandom.so
3650: trying file=/lib/x86_64-linux-gnu/librandom.so
3650: trying file=/usr/lib/x86_64-linux-gnu/tls/x86_64/librandom.so
3650: trying file=/usr/lib/x86_64-linux-gnu/tls/librandom.so
3650: trying file=/usr/lib/x86_64-linux-gnu/x86_64/librandom.so
3650: trying file=/usr/lib/x86_64-linux-gnu/librandom.so
3650: trying file=/lib/tls/x86_64/librandom.so
3650: trying file=/lib/tls/librandom.so
3650: trying file=/lib/x86_64/librandom.so
3650: trying file=/lib/librandom.so
3650: trying file=/usr/lib/tls/x86_64/librandom.so
3650: trying file=/usr/lib/tls/librandom.so
3650: trying file=/usr/lib/x86_64/librandom.so
3650: trying file=/usr/lib/librandom.so

[..]

我剪裁了输出。难怪找不到我们的共享库-所在目录librandom.so不在搜索路径中!解决此问题的最特别的方法是使用LD_LIBRARY_PATH


$ LD_LIBRARY_PATH=. ./main

它可以工作,但不是很轻便。我们不想每次运行程序时都指定lib目录。更好的方法是将依赖项放入文件中, 这就需要设置rpathrunpath


rpath和runpath

rpath并且runpath是我们的运行时搜索路径“清单”中最复杂的项目。可执行文件或共享库的rpath和runpath在.dynamic我们前面介绍的部分中是可选条目。它们都是要搜索的目录列表。



rpath的类型为DT_RPATH, runpath的类型为DT_RUNPATH



rpathrunpath之间的唯一区别是搜索它们的顺序。具体来说,它们与LD_LIBRARY_PATH的顺序: rpath在LD_LIBRARY_PATH之前搜索,而runpath在LD_LIBRARY_PATH之后搜索。这意味着rpath不能用环境变量动态改变,而runpath可以。


设置rpath,看看是否可以让main工作:


$ clang++ -o main main.o -lrandom -L. -Wl,-rpath,.

参数-Wl-rpath逗号分隔将.标志传递给链接器。要进行设置runpath,我们还必须通过--enable-new-dtags参数设置(-Wl,--enable-new-dtags,-rpath,.)。让我们检查一下结果:


$ readelf -d main | grep path
0x000000000000000f (RPATH) Library rpath: [.]

$ ./main

可执行文件可以运行,但是已将其添加.rpath当前的工作目录中。这意味着它将无法从其他目录运行:


$ cd /tmp
$ ~/code/shared_lib_demo/main
/home/nurdok/code/shared_lib_demo/main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

我们有几种解决方法。最简单的方法是复制librandom.so到搜索路径中的目录(例如/lib)。显然,更复杂的方法是我们要执行的操作-指定rpath相对于可执行文件的位置。


$ORIGIN

rpath和runpath中的路径可以是相对于当前工作目录的绝对路径(例如/path/to/my/libs/),但它们也可以是相对于可执行文件的。这是通过使用rpath定义中的$ORIGIN变量来实现的:


$ clang++ -o main main.o -lrandom -L. -Wl,-rpath,"\$ORIGIN"

注意,$ORIGIN不是一个环境变量。如果你设置ORIGIN=/path,它将不起作用。它总是放置可执行文件的目录。



请注意,我们需要对美元符号进行转义(或使用单引号),以便我们的shell不会尝试对其进行扩展。结果是main可以在每个目录下工作并librandom.so正确找到:


$ ./main
$ cd /tmp
$ ~/code/shared_lib_demo/main

让我们使用我们的工具包来确保:


$ readelf -d main | grep path
0x000000000000000f (RPATH) Library rpath: [$ORIGIN]

$ ldd main
linux-vdso.so.1 => (0x00007ffe13dfe000)
librandom.so => /home/nurdok/code/shared_lib_demo/./librandom.so (0x00007fbd0ce06000)
[..]

运行时搜索目录之安全性

如果您从命令行更改了Linux用户密码,则可能使用了该passwd实用程序:


$ passwd
Changing password for nurdok.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

密码被哈希之后存储在受root保护的文件/etc/shadow中,所以问题来了,非root用户如何更改此文件?


答案是passwd程序设置了setuid位,你可以通过ls看到:


$ ls -l `which passwd`
-rwsr-xr-x 1 root root 39104 2009-12-06 05:35 /usr/bin/passwd
# ^--- This means that the "setuid" bit is set for user execution.

这是s(该行的第四个字符)。设置了此权限位的所有程序均以该程序的所有者身份运行。在此示例中,用户是root(该行的第三个单词)。


这与共享库有什么关系? 我们举个例子.


现在我们在libs目录下有了librandom.so,并且我们将main程序的rpath设置为$ORIGIN/libs:


$ ls
libs main
$ ls libs
librandom.so
$ readelf -d main | grep path
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/libs]

正常我们是可以运行main的,但是我们给它设置setuid位,并设置属主为root:


$ sudo chown root main
$ sudo chmod a+s main
$ ./main
./main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

好吧,rpath行不通。让我们尝试设置LD_LIBRARY_PATH


$ LD_LIBRARY_PATH=./libs ./main
./main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

还是不行,这里发生了什么?


出于安全考虑,使用提升的权限运行可执行文件(例如,当setuidsetgid特殊功能等)的搜索路径不同于正常:LD_LIBRARY_PATH被忽略,以及任何路径rpathrunpath包含$ORIGIN


原因是使用这些搜索路径允许利用提升的特权可执行文件以as身份运行root。有关此漏洞利用的详细信息,请参见此处


基本上,它允许您使提升特权的可执行文件加载您自己的库,该库将以root用户(或其他用户)身份运行。以root身份运行自己的代码几乎可以使您完全控制所使用的计算机。


如果您的可执行文件需要提升的特权,则需要在绝对路径中指定依赖项,或将其放置在默认位置(例如/lib)。


这里要注意的重要行为是,对于此类应用程序,ldd我们必须面对:


$ ldd main
linux-vdso.so.1 => (0x00007ffc2afd2000)
librandom.so => /home/nurdok/code/shared_lib_demo/libs/librandom.so (0x00007f1f666ca000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1f663c6000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1f660c0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1f65eaa000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1f65ae5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1f668cc000)

ldd不在乎setuid,它会$ORIGIN在搜索我们的依赖项时扩展。在调试对setuid应用程序的依赖项时,这可能是一个陷阱。


调试备忘单

如果在运行可执行文件时遇到此错误:


$ ./main
./main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

您可以尝试执行以下操作:


  1. 找出缺少哪些依赖项ldd <executable>;
  2. 如果您不能识别它们,则可以通过运行来检查它们是否是直接依赖项readelf -d <executable> | grep NEEDED;
  3. 确保依赖项确实存在。也许您忘了编译它们或将它们移动到libs目录中?
  4. 找出使用来搜索依赖项的位置LD_DEBUG=libs ldd <executable>;
  5. 如果您需要在搜索中添加目录:

临时:将目录添加到LD_LIBRARY_PATH环境变量
嵌入文件中:将目录添加到可执行文件或共享库的目录中,rpath或runpath通过传递-Wl,-rpath,<dir>(for rpath)或-Wl,--enable-new-dtags,-rpath,<dir>(for runpath)。使用$ORIGIN相对于可执行文件的路径。



  1. 如果ldd显示没有依赖项丢失,请查看您的应用程序是否具有提升的特权。如果是这样,ldd可能会撒谎。请参阅上面的安全问题。

原文: https://amir.rachum.com/blog/2016/09/17/shared-libraries/#debugging-cheat-sheet
参考:
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-42444.html
https://www.gnu.org/software/libc/
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
http://unix.stackexchange.com/questions/22926/where-do-executables-look-for-shared-objects-at-runtime
http://www.sco.com/developers/gabi/latest/ch5.pheader.html
https://greek0.net/elf.html
https://en.wikipedia.org/wiki/Rpath
http://blog.lxgcc.net/?tag=dt_rpath
https://cs.nyu.edu/~xiaojian/bookmark/linux/ld_so%20%20Dynamic-Link%20Library%20support.htm
http://unix.stackexchange.com/questions/101467/how-does-the-passwd-command-gain-root-user-permissions
http://nairobi-embedded.org/004_elf_format.html

更多话题 >>

热门话题

System

42 个问题, 7 人关注

更多用户 >>

热门用户

小白菜

2 个问题, 8 次赞同

OS小编

13 个问题, 4 次赞同