Everything you care about in one place

Follow feeds: blogs, news, RSS and more. An effortless way to read and digest content of your choice.

Get Feeder

rutk1t0r.org

rutk1t0r's blog

Get the latest updates from rutk1t0r's blog directly as they happen.

Follow now 78 followers

Latest posts

Last updated over 1 year ago

Linux内核0.11完全注释 关于任务睡眠和唤醒的理解

over 9 years ago

主要理解注释中提到的链表以及缺少几行代码的缘由何为任务调度?学过操作系统的筒子们应该有很深刻的理论了,其实说白了就是从现有可运行的任务中选一个最紧急(或者优先级最高)的任务运行,关于如何定义”最紧急”(优先级最高或者说实时进程)才是调度算法去解决的问题,这里先不分析,Linux 0.11内核调度算法也不是很难。sleep_on()函数没有源代码的可以参阅这里。这里的代码已经有修复了。Linus原来的代码如下:(中文注释乃赵博士所写~)12345678910111213141516171819202122232425262728293031323334353637// 把当前任务置为不可中断的等待状态,并让睡眠队列指针指向当前任务。// 只有明确的唤醒时才会返回。该函数提供了进程与中断处理程序之间的同步机制。函数参数P是等待// 任务队列头指针。指针是含有一个变量地址的变量。这里参数p使用了指针的指针形式'**p',这是因为// C函数参数只能传值,没有直接的方式让被调用函数改变调用该函数程序中变量的值。但是指针'*p'// 指向的目标(这里是任务结构)会改变,因此为了能修改调用该函数程序中原来就是指针的变量的值,// 就需要传递指针'*p'的指针,即'**p'.void sleep_on(struct task_struct **p){struct task_struct...

chromium支持arm64架构验证

over 1 year ago

html2pdf ?参考资料:CentOS系统下内存页Page Size如何从64K切换到4Khttps://bbs.chinauos.com/zh/post/18054背景有一个case是需要在ARM64架构下支持html2pdf,以及crawler功能,其引用的库为puppeteer(或者python下叫pyppeteer),通过检索后了解到google官网没有为ARM64架构支持发行版的二进制包,从别的地方搜索可知ubuntu 18.04默认的发型版带了,因此需要做迁移验证。验证用虚拟化工具安装官方镜像或者直接去云平台服务商购买虚拟机均可以,通过apt等工具装上后,如下:12345678910111213141516171819202122232425262728root@VM-1-28-ubuntu:~# cat /etc/os-release NAME="Ubuntu"VERSION="18.04.6 LTS (Bionic Beaver)"ID=ubuntuID_LIKE=debianPRETTY_NAME="Ubuntu 18.04.6 LTS"VERSION_ID="18.04"HOME_URL="https://www.ubuntu.com/"SUPPORT_URL="https://help.ubuntu.com/"BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"VERSION_CODENAME=bionicUBUNTU_CODENAME=bionicroot@VM-1-28-ubuntu:~#...

psock_tpacket实践

over 1 year ago

抓包原理初识参考资料:https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.10.1.tar.gzhttps://docs.kernel.org/networking/packet_mmap.htmlhttps://www.zhihu.com/question/486178226/answer/2587632732https://jgsun.github.io/2019/01/21/linux-tcpdump/分析 tools/testing/selftests/net/psock_tpacket.c下载内核源码并编译测试程序cd linux-3.10.1/tools/testing/selftests/net && make分析初始化首先定位到pfsocket函数,其中需要初始化一个domain为PF_PACKET,type为SOCK_RAW的套接字,通过分析PF_PACKET是宏定义AF_PACKET一样的值,而在Linux内核的介绍当中AF_PACKET专门用来嗅探流量用的,类似wireshark和tcpdump;当调用到setsockopt的时候,内核对应packet_setsockopt函数,1234567891011121314151617static int pfsocket(int ver){int ret, sock = socket(PF_PACKET...

DIM-SUM学习

over 4 years ago

DIM-SUM内核学习,先跑起来吧。参考资料DIM-SUM仓库缘由之前很早有关注过作者,后面逐渐听说有设计操作系统内核的计划,今年偶然听说出了一本新书,就买来学习了。跑起来拿到书籍后里面有读者服务的二维码,所以就从那里面先拿到了源码包以及《答案.docx》。后续可以直接参考gitee上的教程跑。编译编译少库的问题自行搜索解决即可,我的系统是ubuntu 20.0412345678910111213141516171819202122232425262728293031rutk1t0r@ubuntu:~/dev/dim-sum/dim-sum/src$ ./build.sh CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.shgrep: scripts/../arch/x86/syscalls/syscall_32.tbl: No such...

VPC网络打通研究

almost 5 years ago

云内网络打通参考资料gofrpn2nnps背景在云内多VPC场景下,需要实现多NFV极简+管控+运维+部署。传统的安全管理平台采用平台侧主动推送和纳管NFV组件, 但是在VPC场景下网络打通存在中间的访问控制策略隔离,以及私有网络的暴露面问题。思路正向打通:网络往往采用NAT技术或者代理服务器,将内网的服务暴露出来,但是这样的运维成本较大,且存在安全性问题。 采用VPN技术需要两端都外挂前置设备或者软件。逆向打通:技术上采用将原本的服务端安装一个client_agent,通过反向的先让client_agent接入原本的客户端的server_proxy, 然后代理程序本身实现IP级别或者PORT级别的隧道数据转发,下面分析逆向打通的几个方案。开源方案技术方案优点缺点N2N功能丰富,满足需求,实现IP2IP级别访问采用内核方案,稳定性差NPS功能丰富,控制面安全性较好GPL协议无法商用FRP功能较丰富,apache协议可以商用控制面安全性一般FRP方案分析为了满足商用需求,可以考虑采用FRP作为VPC网络打通数据面的方案,默认监听7000端口。引入另外的独立的控制面来负责FRP的统一管理/升级维护/横向扩展/高可用等,以满足持续迭代的需求。配置方法参考官网教程 直接配置frpc.ini和frps.ini即可因此在client上如何管理好frpc.ini是重点.frps.ini12[common]bind_port = 7000可以选择默认启用tls_only选项以及token。可以启用服务端插件功能获取frpc的接入上下文来实现???问控制。frpc.ini 123456789[common]server_addr = x.x.x.xserver_port = 7000[ssh]type...

Linux内核0.11完全注释 第四章-番外篇

over 9 years ago

本篇将根据实战经验来构建这个简单的多任务内核的运行Bochs安装和配置通过Debian或者RHEL的包管理器直接安装或者源码安装都可以,网上多建议源码安装,说可以开启调试和反汇编功能,我发现都差不多,至于Win平台的直接点击点击即可。按照网???的一些教程将拷贝一份配置文件或者直接文本新建一个,将romimage和vgaromimage的路径配置好,我的配置如下,删除了很多没啥用的。看启动文件可知道仅仅需要一个设备即可完成。Image是后面编译链接后用dd命令写入的文件。123456romimage: file=$BXSHARE/BIOS-bochs-latestmegs: 16vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latestfloppya: 1_44=Image, status=insertedboot: alog: bochsout.txt生成启动文件首先由于我没有Get到原网站的资料,只好硬着头皮根据书本的后面章节来推敲了。 我根据上图自己”凑合着”编写Makefile文件。12345678910111213141516171819202122232425262728293031323334353637383940rutk1t0r@Rutk1t0r:example_for_multi_tasks$ cat Makefile Image...

golang init

about 5 years ago

拥抱追求高效率生产的云原生时代参考资料 go在线教程 leetcode区间合并安装此处可以直接搜索网上的教程,建议用goland+插件,可以极大地提高生产效率,试用补丁方案在这里参考。小试牛刀采用leetcode刷题学习,题目是要求合并若干区间数组以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。这道题在现实情况的工程问题可能对应着需要找出用户配置的IP端,可以合并下发到数据面。算法思路所以解算法题最先要想到如果达到了目标状态,那些数据应该是什么样的我们用数组 merged 存储最终的答案。首先,我们将列表中的区间按照左端点升序排序。然后我们将第一个区间加入...

Linux内核0.11完全注释 第四章

over 9 years ago

介绍Intel 80X86保护模式及其编程80X86基础知识eflags标志寄存器几个系统标志的作用,其中需要说明的IF标志位也是可以控制的,通过汇编指令sti和cli。需要特权才能执行,否则产生异常。Intel芯片的设计者增加这几个标志位的目的是为了配合操作系统更好地管理系统资源以及安全性的提升,诚然操作系统设计者可以不用理会部分标志,但是有这些硬件机制使得程序流程执行起来更加快速。 内存管理寄存器由于80386及以后的CPU的主要工作状态均采用保护模式(相对于8086时代的实模式),其实所谓的保护最主要的还是保护内存,DOS时代的病毒太过于泛滥的主要原因之一是当时8086的内存保护几乎为0。因此真正懂得程序布局和设计的早期hacker可以随意”摆弄”计算机。而保护模式便要大大提高门槛了,把恶意指令限制在CPU内部解决而不直接通过系统总线送往内存控制器。 GDTR全局描述符表寄存器,CPU内部,48位,保存GDT的32位线性基地址和16位表长度(字节)使用汇编指令LGDT和SGDT来加载和保存GDTR的内容刚刚上电初始化base为0,len为0xFFFFboot阶段进入保护模式过程中必须被赋值,因为一旦进入保护模式便要一直用它IDTR中断描述符寄存器,CPU内部,48位,保存IDT的32位线性地址和16位表长度(字节为单位)LIDT和SIDT上电同上也是必须被设置,但是初始化过程中可以关闭中断使得如同空设。而后必须填充好。LDTR不仅包含和GDTR的48位,还有段属性以及选择子可用于任务切换的局部空间寻址TR同上,但描述符部分属性和内容更多控制寄存器CRO主要含有控制处理器模式和状态的系统控指标志协处理器的相关控制(浮点计算)保护模式开启和关闭以及分页模式的启毕 CR1 Intel保留CR2异常的线性地址保存CR2,便于实现虚拟内存CR3PDBR,高20位为页目录基地址,低12位暂时保留。任务切换时被更新,分页机制的第一基点保护模式内存管理地址变换段的定义Intel芯片中的分段机制必须开启,但是软件开发人员可以采用平坦模式,即配置分段机制的各个选择子描述符基址为0,长度为4G,好处是便于后期编程。段描述符GDT 8字节,含段基址,段限长及段属性,可表示(类似继承)成各种段,包括代码段,数据段,tss段等等由GDTR指向,一般确定后不会更改地址,可以增加项目 - 第一项约定必须为空LDT属性差不多同上,但只能包含成任务的代码段和数据段等,不包含特殊系统段。第一项可以用段选择符以前的段寄存器并不直接用于寻址,而是提供index,并隐含不可直接操作的Cache部分,只有在切换的时候才更新,加快处理速度。各个8字节的描述符概括图,主要三个字段的段基址、段限长和段属性一般由编译器、链接器、加载器和操作系统来创建。详细定义参考Intel开发者手册等。开发者需要理解芯片设计者的本意而后根据自己的实际情况来创建。除了代码段、数据段和堆栈段等一般的段还有系统描述符类型,包括LDT、TSS、调用门、中断门、陷阱门和任务门。分页机制作为分段机制的补充和”串联选择”,如果不开启则分段过程后地址将直接放在系统总线上。提供OS高级功能虚拟内存的硬件平台。提供加强的内存属性保护各种保护措施段级保护所有违反保护的操作都将导致产生一个异常,要么进行异常过程处理,要么down掉Reset。段界限检查主要是GDT、LDT、IDT长度限制和常规描述符的段限长控制段类型检查谈谈绕过方法的个人猜想,当不讨论分页机制时候或者说没有开启分页的时候,分段机制作为最核心的内存保护而存在于CPU内部。诸如下面的保护都是在CPU内部完成的,当我们想要修改内存中数据怎么办呢?首先需要取得所有权限,即0特权级,而后建立新的描述符指向我们想要修改的内存区域(例如某某进程的密码等等),而后即可绕过”他人的防守”径直地向系统总线上发控制信号来读写内存数据。而当其他进程再去操作的时候拿到的东西已经被”掉过包”了。这也是为什么内存攻防中能够提权的漏洞越来越得到重视的原因之一,由于shellcode等已经被”共享”得差不多了,也大同小异。为了获取系统权限,必须不断Fuzzing冲???内存,突破程序逻辑….根据描述符属性字段中的tpye进行匹配当一个描述符的选择符被加进段寄存器时CS寄存器只能被加载进一个可执行段的选择符;不可读可执行的选择符不能加进数据段选择子;只有可写数据段才能被加进SS寄存器 当指令访问段时任何指令不能写一个可执行段任何指令不能写一个可写位没有置位的数据段任何指令不能读一个可执行段,除非可执行段设置了可读标志特权级检查CPL的值即为CS和SS寄存器的低2位(保护模式中要求任何时候代码段和堆栈段的CPL一致) 关于更详细和细致地代码段特权级检查可参考代码一致性和非一致性数据段中主要是CPL、RPL和DPL的逻辑比较属性字段的匹配指令集限制主要是非特权程序不能执行特权指令页级保护中断和异常处理硬件机制和软件处理两者完美结合才能完成一个良好的系统的设计把中断看作是另一个控制流程即可,从逻辑上符合人类思考。需要提前填充处理过程的地址,处理器自动加载并跳转执行。中断源来自硬件(INTR和NMI引脚)和软件(指令各种内部错误和主动发起的int n软中断)中断优先级规定...

Linux内核0.11完全注释 第四章-番外篇

over 9 years ago

本篇将根据实战经验来构建这个简单的多任务内核的运行Bochs安装和配置通过Debian或者RHEL的包管理器直接安装或者源码安装都可以,网上多建议源码安装,说可以开启调试和反汇编功能,我发现都差不多,至于Win平台的直接点击点击即可。按照网上的一些教程将拷贝一份配置文件或者直接文本新建一个,将romimage和vgaromimage的路径配置好,我的配置如下,删除了很多没啥用的。看启动文件可知道仅仅需要一个设备即可完成。Image是后面编译链接后用dd命令写入的文件。123456romimage: file=$BXSHARE/BIOS-bochs-latestmegs: 16vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latestfloppya: 1_44=Image, status=insertedboot: alog: bochsout.txt生成启动文件首先由于我没有Get到原网站的资料,只好硬着头皮根据书本的后面章节来推敲了。 我根据上图自己”凑合着”编写Makefile文件。12345678910111213141516171819202122232425262728293031323334353637383940rutk1t0r@Rutk1t0r:example_for_multi_tasks$ cat Makefile Image...

Linux内核0.11完全注释 第五章

over 9 years ago

久违的章节,简介Linux内核体系结构OS组成部分所谓内核,主要是运行起来之后与计算机硬件交互,实现对硬件部件的编程控制和接口操作,调度对硬件资源的访问,并且为计算机的用户程序提供一个高级环境和对硬件的虚拟接口。个人认为纯粹地看就是一大堆的数据结构和策略算法以及驱动程序,当然为了能够发挥作用必须得提供接口给用户等等。宏内核模型灵活运用计算机体系里最重要的”分层”思想,可以很好地解决大问题,此时可以揣摩计算机网络等等服务提供者和调用者即“客户-服务”思想让人容易想到C++类等等机制Linux内核体系结构主要模块进程调度内存管理文件系统进程间通信网络接口内核对内存的管理和使用内存分布视图其中显存和ROM BIOS部分是由于工程师在集成PC的时候把地址空间分给了它们。分段机制在Intel处理器中必须开启,但是软件工程师可以采用”平坦模式”寻址使得没有分段分页机制需要大量的”铺垫”才能启用,并且为mm子系统提供支持内存地址空间概念虚拟地址:由程序运行时候CPU内部的段选择子和段内偏移组成,因为没有直接用来访问物理内存(区别于8086时代),因此成为虚拟地址。虚拟地址空间由GDT和LDT映射组成,理论上的空间总量(注意不要又扯到物理地址去了,不要管地址总线多少根)为2^13*4G=64T。逻辑地址即可理解为虚拟地址。线性地址:虚拟地址和物理地址变换之间的中间层,是处理器可以寻址的内存空间。即相应的段基址加上偏移地址即可,相当于去描述符表中或者高速缓存中取了一次数据后合并后的地址。如果此时没有启用分页机制,则线性地址即为物理地址,CPU直接放在地址总线上去内存中存取数据。物理地址:即CPU外部总线上的地址信号,如果开启分页机制,则线性地址必须经过CR3、页目录和页表等转换才能送到地址总线上。虚拟存储:即OS使得CPU对所有内存的寻址加一个”hook”,以满足最大化的需求。Linux具体的内存分布虽然代码段和数据段共用一个内存空间,但是对于当时的版本来说安全性不是首要考虑的,因此一切以方便工程师编程为出发点。各种人工的定义也是为了方便操作。内核代码段和数据段三种地址转换在head.s程序的初始化过程中把内核代码段和数据段都设置为16M的段,两个段重叠并且线性地址都为0开始到0xFFFFF。在这16M的内核空间中包括所有的代码、内核段表、页目录表和内核的二级页表、内核局部数据以及内核临时堆栈(将被用作任务0的用户堆栈)。16M的空间仅仅需要4个页表(16M/1024/4K=4),一个页4*1024字节,一个页目录项包括1024个页表,一个页表含有1024个页,因此仅仅需要一个页目录表和4个页表即可。(默认情况Linux 0.11最多可以管理16MB的物理内存)小于16M的物理内存也可以运行Linux 0.11,在init/main.c中也仅仅映射了0-16MB的内存范围,多了也用不到,除非自己修改内核代码,增加页表。任务0空闲进程,主要执行pause()系统调用任务1init进程其他任务用户主动申请的内存由task_struct结构体(PCB)维护的brk值满足C库中malloc函数的动态堆内存分布需求。内核仅仅更新brk值并延迟等到访问页失败的时候才分配真正的空间free释放的时候也仅仅是告知内核将对应的页标记为空闲,以被程序再次使用,当进程结束的时候才回收。中断机制采用外置8259A芯片来管理多级优先级中断。中断请求号对应实际的信号引脚,中断号将由PIC通过数据总线送往CPU。中断门和陷阱门的区别在于对EFLAGS中的IF的影响,进入到中断门后CPU会自动复位IF以防止其他中断干扰,随后的iret也会自动从堆栈中恢复,而陷阱门则不会影响IF。系统调用syscalls是Linux内核与上层应用程序进行交互通信的唯一接口,约定调用软中断号为0x80(int 0x80)。参数传递为eax表示调用功能号,ebx、ecx、edx为参数,详情参考源码。0.11版本的多用C嵌入汇编实现0.11版本的内核约定进程在内核态运行不会被调度程序切换即进程在内核态运行时是不可抢占的。后期内核版本由于性能需求必须被设计成可抢占的。Linux进程控制任务主要数据结构123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869struct i387_struct {longcwd;longswd;longtwd;longfip;longfcs;longfoo;longfos;longst_space[20];/* 8*10 bytes for each FP-reg...

Linux内核0.11完全注释 第六章

over 9 years ago

迷你bootloader部分从ROM BIOS处接手过来加载内核代码需要参考ROM BIOS的中断使用手册,从硬盘加载数据以及控制显示设备等MBR的508、509偏移字节处保存根设备号参考书籍作者的资料中《Linux内核源代码漫游》 硬盘设备号全局参数PIC 8295A中断芯片配置相当复杂,建议直接用现成的吧。system模块映像小结本章跟以前分析的小程序大同小异,只不过开启了分页机制,但是也是很简单的换算。

Linux内核0.11完全注释 第七章

over 9 years ago

init进程来了内核初始化流程着重分析”move_to_user_mode()”的前前后后move_to_user_mode()宏定义这是一段嵌入汇编,gcc在预处理的时候就会完全替代掉。本质是模拟中断返回从内核态转到用户态,但是控制流还是下面那段。相当于虽然从内核态转到用户态但是由于选择子指向的是同一段物理内存空间,所以CPU执行流看起来还是没有什么”异常”。根据压栈顺序可以知道用户态cs为0x0f,EIP为iret指令下面的标号1处,功能是仅仅将用户态的局部段选择子值送往各个数据段选择器。而后就会执行fork()函数。下面去看一下任务0的全局描述符表的项是如何加载进去的。1234567891011121314#define move_to_user_mode() \__asm__ ("movl %%esp,%%eax\n\t" \"pushl $0x17\n\t" \"pushl %%eax\n\t" \"pushfl\n\t" \"pushl $0x0f\n\t"...