无垠之码

深度剖析代码之道


Linux内核安全模块深入剖析-读书笔记

本书相关章节分成以下部分:

  • 自主访问控制
  • 强制访问控制
  • 完整性保护
  • 审计和日志
  • 加密
  • 其他

引言


作者在引言中抛出如下问题:

  1. 开源是否意味着安全或更安全, 开源意味着自主可控, 代码暴露程度高单, 问题代码会更早发现(重大漏洞由十几年前问题代码导致)
  2. 功能丰富是否会导致漏洞代码越多, 功能手机与智能手机的安全忧虑
  3. 安全与漏洞挂钩, 漏洞与代码缺陷的关系?

作者未给出明确的定义, 但引用国际通用对计算机安全特性的总结:CIA(私密性,完整性,可用性) 常用应对安全挑战的方法: 隔离、 控制、 混淆、 监视

隔离, 系统在不同层次实现隔离, 阻断内部与外部的交互, 导致沙箱技术
控制, 控制在针对系统内部, 通过系统代码内在逻辑和安全策略来维护信息流动和信息改变
混淆, 明明可以接触数据却无法还原信息, 加密就是一种混淆
监视, 监视的作用是间接的, 不改变事物发展状态客观记录

美国在1970前后提出两个安全模型, BLP和BIBA模型, 解决信息的私密性和完整性
BLP着力解决私密性, 参考军方保密原则, 总结为两句话, 禁止上读, 禁止下写, 数据分级, 某部门只能读取本部门和级别低于本部门的相关数据
BIBA, 总结为禁止上写, 禁止下读, 数据分级, 下级不能写上级数据, 上级不能读取下级数据, 重点解决完整性问题

多用户系统, 基于角色的访问控制RBAC, 用户属于不同角色, 基于角色赋予权限
实际系统用户数量有限, 引出类型增强访问控制模型TE(Type Enforcement), 控制对象不再是人,或角色, 而是进程, 进程属于不同的类型, 不同的类型拥有不同的访问权限

不同的安全防护范式, 传统计算机安全与可信理论

当前计算安全现状:

  1. 安全并不是系统设计的最初目标
  2. 专业安全研究员眼中, ISO并不比Android更安全, 安全不仅仅是一个技术问题也是一个管理问题
  3. 安全性与易用性的矛盾

引言最后, 作者描述Linux内核安全概貌, 总结当前存在的一些问题: 1. 应用问题(基于能力的特权机制,未推广) 2. 整合问题, 内核安全模块分散与各个子系统中, 整合安全子模块, 加固系统

Read more...

cgroup漫谈

cgroup-v1是由google工程师在内核v2.6.24合入,用来限制控制进程资源(如CPU、内存)使用的一种资源控制机制。内核4.5版本时cgroup-v2发布,虽然现在内核主线版本已发布至6.13但ubuntu-20.04的使用5.15的内核版本,系统中cgroup的v1和v2版本共存。限于篇幅本文主要介绍内核中cgroup-v1相关的内容。

cgroup中cgroupfs是Linux内核文件系统中的一个子系统,用于限制、记录和隔离进程组的资源使用。通过在cgroupfs上创建、删除和挂载cgroup,可配置和管理容器化应用程序的资源限制和优先级。cgroupfs亦可看作一种api文件系统,因为内核关于cgroup的相关操作接口通过该文件系统暴露给用户态进程使用。本篇博客以操作系统在开机时如何挂载cgroupfs文件系统为切入点,介绍cgroup的相关概念和技术原理和内核cgroup的实现。

用户空间


开机挂载

Linux系统的启动流程(基于UNIX System V4),其中主要包括:硬件初始化->操作系统加载->初始化内核->用户空间init进程->开机脚本,5个阶段,详见man 7 boot文档。基于systemd的init系统(诸如ubuntu-18+,centos-7+系统),systemd除了扮演操作系统服务管理器维护用户空间服务的角色,还在开机时刻引导系统启动必要服务,使系统进入可用状态,即systemctl get-default设置的开机目标。多用户环境用户管理器实例会通过user@.service(5)服务自动启动,此时systemd会启动一个用户实例,管理用户单元。

image

system-bootup流程图展示graphical.target目标所包含的基本流程,可以看出其相关的文件系统挂载工作在sysinit.target中基本已全部完成,其他与网络相关的文件系统的挂载操作在remote-fs目标中完成。

systemd-v245源码

mk-sbuild --arch=amd64 focal
apt-get source systemd
sbuild -d focal ./systemd_245.4-4ubuntu3.24.dsc
cc -Isystemd@exe -I. -I.. -Isrc/basic -I../src/basic -Isrc/boot -I../src/boot -Isrc/shared -I../src/shared -Isrc/systemd -I../src/systemd -Isrc/journal -I../src/journal -Isrc/journal-remote -I../src/journal-re mote -Isrc/nspawn -I../src/nspawn -Isrc/resolve -I../src/resolve -Isrc/timesync -I../src/timesync -I../src/time-wait-sync -Isrc/login -I../src/login -Isrc/udev -I../src/udev -Isrc/libudev -I../src/libudev -Isrc/core -I.. /src/core -Isrc/shutdown -I../src/shutdown -I../src/libsystemd/sd-bus -I../src/libsystemd/sd-device -I../src/libsystemd/sd-event -I../src/libsystemd/sd-hwdb -I../src/libsystemd/sd-id128 -I../src/libsystemd/sd-netlink -I. ./src/libsystemd/sd-network -I../src/libsystemd/sd-resolve -Isrc/libsystemd-network -I../src/libsystemd-network -I../ -I/usr/include/libmount -I/usr/include/blkid -flto -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BIT S=64 -std=gnu99 -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Werror=undef -Wlogical-op -Wmissing-include-dirs -Wold-style-definition -Wpointer-arith -Winit-self -Wfloat -equal -Wsuggest-attribute=noreturn -Werror=missing-prototypes -Werror=implicit-function-declaration -Werror=missing-declarations -Werror=return-type -Werror=incompatible-pointer-types -Werror=format=2 -Wstrict-prototype s -Wredundant-decls -Wmissing-noreturn -Wimplicit-fallthrough=5 -Wshadow -Wendif-labels -Wstrict-aliasing=2 -Wwrite-strings -Werror=overflow -Werror=shift-count-overflow -Werror=shift-overflow=2 -Wdate-time -Wnested-exte rns -Wno-error=nonnull -Wno-maybe-uninitialized -ffast-math -fno-common -fdiagnostics-show-option -fno-strict-aliasing -fvisibility=hidden -fstack-protector -fstack-protector-strong --param=ssp-buffer-size=4 -ffunction-s ections -fdata-sections -Werror=shadow -include config.h -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIE -pthread -MD -MQ 'syst emd@exe/src_core_main.c.o' -MF 'systemd@exe/src_core_main.c.o.d' -o 'systemd@exe/src_core_main.c.o' -c ../src/core/main.c
cc -o systemd 'systemd@exe/src_core_main.c.o' -flto -Wl,--as-needed -Wl,--no-undefined -pie -Wl,-z,relro -Wl,-z,now -fstack-protector -Wl,--gc-sections -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-pro tector-strong -Wformat -Werror=format-security -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--start-group src/core/libcore.a src/core/libcore-shared.a src/shared/libsystemd-shared-245.so -pthread -lrt /usr/lib/x86_64-linux- gnu/libseccomp.so /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libselinux.so /usr/lib/x86_64-linux-gnu/libmount.so /usr/lib/x86_64-linux-gnu/libblkid.so -lpam /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64- linux-gnu/libaudit.so /usr/lib/x86_64-linux-gnu/libkmod.so /usr/lib/x86_64-linux-gnu/libapparmor.so -Wl,--end-group '-Wl,-rpath,$ORIGIN/src/core:$ORIGIN/src/shared' -Wl,-rpath-link,/<<PKGBUILDDIR>>/build-deb/src/core -Wl ,-rpath-link,/<<PKGBUILDDIR>>/build-deb/src/shared

整个编译系统,systemd选择使用的meson构建(meson构建系统的基本用法在其他博客文章中已介绍),通过编译日志发现,systemd由src/core/main.c源码编译。调用过程如下所示:

Read more...

用户态Linux

UML将Linux内核编译为一个可执行文件,直接在宿主机的用户空间中运行,无需硬件虚拟化如KVM或VMware支持。每个UML实例是一个独立的进程,拥有自己的虚拟内核和用户空间,主要用于调试、测试、虚拟化和隔离环境等场景

slirp_concept

sudo apt-get install screen uml-utilities
./linux ubda=rootfs.img umid=debian mem=512M
screen /dev/pts/x   
mount / -o remount,rw
uml_mconsole debian   {>>uml控制终端<<}

0.编译kernel


make ARCH=um SUBARCH=x86_64 defconfig
make ARCH=um SUBARCH=x86_64 -j4

1.rootfs构造


truncate -s 128G rootfs.img
mkfs.ext4 rootfs.img
sudo mount -o loop rootfs.img /mnt
sudo debootstrap stable /mnt http://ftp.cn.debian.org/debian
sudo make modules_install INSTALL_MOD_PATH=/mnt ARCH=um SUBARCH=x86_64

2.网络设置


2.1legacy网络

网络配置一般形式: eth<n>=<transport>,<transport args>,其中ethn表示uml实例中网络接口名称,transport表示host支持的网络后端。

  • ethertap
  • tuntap
  • multicast
  • a switch daemon
  • slip
  • slirp
  • pcap

ethertap

Ethertap is the general mechanism on 2.2 for userspace processes to exchange packets with the kernel.

Read more...

内核熵池

1.熵的定义


熵一般指的是一个系统的混乱程度。热力学中热力熵指分子无规则运动的激烈程度,分子无规则运动越激烈热力熵值越高。信息论中使用信息熵来描述系统的不确定性,信息熵越大,表明系统所含有用信息量越大,不确定度越大。

2.内核实现


Linux内核维护了一个熵池用来收集来自设备驱动程序和其它来源的系统噪音,这些设备噪音作为系统熵。系统噪音可以通过很多参数来评估,如内存的使用,文件的使用量,不同类型的进程数量等等。同时许多现代处理器或主板上带有硬件随机数生成器(如Intel的RDRAND和RDSEED指令,AMD的RNG等)。这些硬件可以产生高质量的随机数,内核可以直接从这些硬件设备获取随机数据。

文档描述[2]

内核文档中关于"随机"相关参数,man手册(man 4 random),sysctl -a -r 'kernel.random\..*':

  • boot_id: 每次启动时生成,启动后不再变化,与journalctl –list-boots展示一致;
  • uuid: 每次读取的时候生成,可以作为uuid的发生器;
  • entropy_avail: 熵池中有效熵的位数;
  • urandom_min_reseed_secs: 该字段已过时(决定urandom pool reseeding的时间间隔);
  • poolsize: 熵池大小,2.4版本内核可设置[32|64|…|2048],2.6后默认256只读;
  • write_wakeup_threshold: 熵池有效熵数目低于该参数, 唤醒试图向/dev/random写入的进程;

mknod命令可以创建random|urandom设备, mknod /dev/[random|urandom] c 1 [8|9]

系统启动早期,由于启动流程相对固定,实际熵池中有效熵不足(entropy-starved systems),于是在启动关机时读取一段随机数据,在系统启动时加载增加系统熵质量。

  1. 基于systemv-init操作系统

在/etc/rc.d/init.d/random或/etc/rcb.d/rc.local存在如下脚本

echo "Initializing random number generator..."
random_seed=/var/run/random-seed
if [ -f $random_seed ]; then
        cat $random_seed >/dev/urandom
else
        touch $random_seed
fi
chmod 600 $random_seed
dd if=/dev/urandom of=$random_seed count=1 bs=512

echo "Saving random seed..."
random_seed=/var/run/random-seed
touch $random_seed
chmod 600 $random_seed
dd if=/dev/urandom of=$random_seed count=1 bs=512
  1. 基于systemd的操作系统

基于systemd的操作系统(centos-7+, ubuntu-18+),使用systemd-random-seed服务完成随机种子的保存与加载功能,systemd-random-seed源码考虑的更加全面,参见文献[4]

Read more...

valgrind高级主题

客户端请求机制


特殊宏定义

Valgrind特殊宏,依据相关功能分别定义于valgrind.h、memcheck.h、callgrind.h、helgrind.h头文件中。

注意:

  1. VALGRIND_CLO_CHANGE宏提交于3a803036f719,此前版本的Valgrind不支持

    valgrind –help-dyn-options: dynamically changeable options: -v –verbose -q –quiet -d –stats –vgdb=no –vgdb=yes –vgdb=full –vgdb-poll –vgdb-error –vgdb-stop-at –error-markers –show-error-list -s –show-below-main –time-stamp –trace-children –child-silent-after-fork –scheduling-quantum –trace-sched –trace-signals –trace-symtab –trace-cfi –debug-dump=syms –debug-dump=line –debug-dump=frames –trace-redir –trace-syscalls –sym-offsets –progress-interval –merge-recursive-frames –vex-iropt-verbosity –suppressions –trace-flags –trace-notbelow –trace-notabove –profile-flags –gen-suppressions=no –gen-suppressions=yes –gen-suppressions=all –errors-for-leak-kinds –show-leak-kinds –leak-check-heuristics –show-reachable –show-possibly-lost –freelist-vol –freelist-big-blocks –leak-check=no –leak-check=summary –leak-check=yes –leak-check=full –ignore-ranges –ignore-range-below-sp –show-mismatched-frees –show-realloc-size-zero

  2. Valgrind错误分类

    • Illegal read / Illegal write errors
    • Use of uninitialised values
    • Use of uninitialised or unaddressable values in system calls
    • Illegal frees
    • When a heap block is freed with an inappropriate deallocation function
    • Overlapping source and destination blocks
    • Fishy argument values
    • Realloc size zero
    • Memory leak detection(a leak is only counted as a true error if –leak-check=full is specified)

valgrind.h相关宏

  • RUNNING_ON_VALGRIND: 判断环境是否运行于Valgrind模拟的CPU环境,返回Valgrind嵌套层数。
  • VALGRIND_DISCARD_TRANSLATIONS:
  • VALGRIND_COUNT_ERRORS: 返回Valgrind发现的错误数目。
  • VALGRIND_MALLOCLIKE_BLOCK: 如果程序的内存管理非标准库函数malloc、new、new[], valgrind memcheck内存追踪将失效。使用该宏追踪非标准分配器分配的内存。
  • VALGRIND_FREELIKE_BLOCK:
  • VALGRIND_RESIZEINPLACE_BLOCK: 通知Valgrind工具分配的块的大小已被修改,但其地址没有变化。
  • VALGRIND_CREATE_MEMPOOL, VALGRIND_DESTROY_MEMPOOL, VALGRIND_MEMPOOL_ALLOC, VALGRIND_MEMPOOL_FREE, VALGRIND_MOVE_MEMPOOL, VALGRIND_MEMPOOL_CHANGE, VALGRIND_MEMPOOL_EXISTS
  • VALGRIND_NON_SIMD_CALL: 命令Valgrind在CPU上执行指定函数。函数支持0-3个参数。
  • VALGRIND_PRINTF: 打印printf风格的消息至Valgrind日志文件。消息使用**pid**作为消息前缀。
  • VALGRIND_PRINTF_BACKTRACE: VALGRIND_PRINTF类似,但在打印消息后立即打印堆栈回溯信息。
  • VALGRIND_MONITOR_COMMAND: 执行Valgrind监控指令。指令有效返回0,否则返回-1。
  • VALGRIND_CLO_CHANGE: 程序中动态改变Valgrind部分参数。(新版本支持)
  • VALGRIND_STACK_DEREGISTER:
  • VALGRIND_STACK_CHANGE: 通知Valgrind之前注册过的堆栈发生改变。
  • VALGRIND_STACK_REGISTER: 通知Valgrind参数start和end之间是唯一的栈空间,返回的标识符作为其他VALGRIND_STACK_*函数的参数使用。Valgrind使用该信息来确定堆栈指针的更改是由于函数调用还是线换,如果堆栈指针的更改发生在注册的堆栈内,则认为是函数调用。如果堆栈指针的更改发生在未注册的堆栈内,则Valgrind将认为该更改是切换到新线程。Valgrind本身是基于操作系统的内存调试工具,可能对协程的堆栈存在一些困难或不完整。这个选项可以帮助Valgrind更准确地识别堆栈信息,从而改善Valgrind对于用户级线程包情境下的堆栈跟踪和错误报告的准确性。(Unfortunately, this client request is unreliable and best avoided)

memcheck.h相关宏

  • VALGRIND_MAKE_MEM_NOACCESS:
  • VALGRIND_MAKE_MEM_UNDEFINED:
  • VALGRIND_MAKE_MEM_DEFINED:
  • VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE:
  • VALGRIND_CREATE_BLOCK:
  • VALGRIND_DISCARD:
  • VALGRIND_CHECK_MEM_IS_ADDRESSABLE:
  • VALGRIND_CHECK_MEM_IS_DEFINED:
  • VALGRIND_CHECK_VALUE_IS_DEFINED:
  • VALGRIND_DO_LEAK_CHECK:
  • VALGRIND_DO_ADDED_LEAK_CHECK:
  • VALGRIND_DO_CHANGED_LEAK_CHECK:
  • VALGRIND_DO_QUICK_LEAK_CHECK:
  • VALGRIND_COUNT_LEAKS:
  • VALGRIND_COUNT_LEAK_BLOCKS:
  • VALGRIND_GET_VBITS:
  • VALGRIND_SET_VBITS:
  • VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE:
  • VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE:

callgrind相关宏

  • CALLGRIND_DUMP_STATS
  • CALLGRIND_DUMP_STATS_AT
  • CALLGRIND_ZERO_STATS
  • CALLGRIND_TOGGLE_COLLECT
  • CALLGRIND_START_INSTRUMENTATION
  • CALLGRIND_STOP_INSTRUMENTATION

helgrind.h相关宏

  • VALGRIND_HG_MUTEX_INIT_POST
  • VALGRIND_HG_MUTEX_LOCK_PRE
  • VALGRIND_HG_MUTEX_LOCK_POST
  • VALGRIND_HG_MUTEX_UNLOCK_PRE
  • VALGRIND_HG_MUTEX_UNLOCK_POST
  • VALGRIND_HG_MUTEX_DESTROY_PRE
  • VALGRIND_HG_SEM_INIT_POST
  • VALGRIND_HG_SEM_WAIT_POST
  • VALGRIND_HG_SEM_POST_PRE
  • VALGRIND_HG_SEM_DESTROY_PRE
  • VALGRIND_HG_BARRIER_INIT_PRE
  • VALGRIND_HG_BARRIER_WAIT_PRE
  • VALGRIND_HG_BARRIER_RESIZE_PRE
  • VALGRIND_HG_BARRIER_DESTROY_PRE
  • VALGRIND_HG_CLEAN_MEMORY
  • VALGRIND_HG_CLEAN_MEMORY_HEAPBLOCK
  • VALGRIND_HG_DISABLE_CHECKING
  • VALGRIND_HG_ENABLE_CHECKING
  • VALGRIND_HG_GET_ABITS
  • VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN
  • ANNOTATE_CONDVAR_LOCK_WAIT
  • ANNOTATE_CONDVAR_WAIT
  • ANNOTATE_CONDVAR_SIGNAL
  • ANNOTATE_CONDVAR_SIGNAL_ALL
  • ANNOTATE_HAPPENS_BEFORE
  • ANNOTATE_HAPPENS_AFTER
  • ANNOTATE_HAPPENS_BEFORE_FORGET_ALL
  • ANNOTATE_PUBLISH_MEMORY_RANGE
  • ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
  • ANNOTATE_NEW_MEMORY
  • ANNOTATE_PCQ_CREATE
  • ANNOTATE_PCQ_DESTROY
  • ANNOTATE_PCQ_PUT
  • ANNOTATE_PCQ_GET
  • ANNOTATE_BENIGN_RACE
  • ANNOTATE_BENIGN_RACE_SIZED
  • ANNOTATE_IGNORE_READS_BEGIN
  • ANNOTATE_IGNORE_READS_END
  • ANNOTATE_IGNORE_WRITES_BEGIN
  • ANNOTATE_IGNORE_WRITES_END
  • ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
  • ANNOTATE_IGNORE_READS_AND_WRITES_END
  • ANNOTATE_TRACE_MEMORY
  • ANNOTATE_THREAD_NAME
  • ANNOTATE_RWLOCK_CREATE
  • ANNOTATE_RWLOCK_DESTROY
  • ANNOTATE_RWLOCK_ACQUIRED
  • ANNOTATE_RWLOCK_RELEASED
  • ANNOTATE_BARRIER_INIT
  • ANNOTATE_BARRIER_WAIT_BEFORE
  • ANNOTATE_BARRIER_WAIT_AFTER
  • ANNOTATE_BARRIER_DESTROY
  • ANNOTATE_EXPECT_RACE
  • ANNOTATE_NO_OP
  • ANNOTATE_FLUSH_STATE

用法举例

以下代码片段基本涵盖上述宏如何使用

Read more...
Previous Page 4 of 4