我对Linux内核了解不多,有一些疑问。
将内核内存与用户空间内存分开的主要目的是什么?确保用户应用程序不会对内核做任何坏事?
用户级应用程序有多少种方法可以将控制权转移到内核?我能想到的包括(1)调用系统调用,(2)将内存映射到内核(但我认为mmap()也是一个系统调用),以及(3)加载内核模块(但我猜是lsmod还调用一些系统调用)。我对么?还有其他方法我错过了吗?
有多少种攻击内核的方法?我可以简要介绍一下他们吗?
如果我获得了root权限,是否意味着我完全控制了内核?也就是说,我可以对内核和硬件做任何我想做的事情?还是我对内核的权力仍然有限?
如果有人能帮我找出这些问题的答案,我将不胜感激。
手册页wait(2)指出,如果指定进程不是调用进程的子进程,waitpid系统调用将返回ECHILD错误。为什么是这样?等待非子进程会产生某种安全问题吗?为什么在非子进程上实现等待是困难或不可能的,是否存在技术原因?
set*gid()除了极少数情况外,各种系统调用都需要特权才能更改组。将主要组更改为进程的补充组之一似乎不是其中之一,这意味着newgrp/sg命令需要提升权限才能切换主要组。
是否有一个原因,为什么setgid()/ setegid()/ setregid()/setfsgid()不允许没有PRIVS切换到补充组?如果是,原因是什么?
当我尝试
strace ping google.com
Run Code Online (Sandbox Code Playgroud)
或者
strace ls
Run Code Online (Sandbox Code Playgroud)
或者
even strace curl <domain>
Run Code Online (Sandbox Code Playgroud)
前两个系统调用总是,
execve("/usr/bin/curl", ["curl", "google.com"], 0x7ffecf1bc378 /* 61 vars */) = 0
brk(NULL) = 0x55f553c49000
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我,当我执行任何操作时,execve 是否总是第一个系统调用?
我读了这个手册页,https://linux.die.net/man/2/execve
但不明白它execve到底是系统调用还是可执行程序?
我正在尝试学习操作系统概念。这是两个简单的Python代码:
while True:
pass
Run Code Online (Sandbox Code Playgroud)
和这个:
from time import sleep
while True:
sleep(0.00000001)
Run Code Online (Sandbox Code Playgroud)
问题:为什么运行第一个代码时 CPU 使用率为 100%,但运行第二个代码时 CPU 使用率约为 1% 到 2%?我知道这可能听起来很愚蠢,但为什么我们不能实施类似的事情sleep在不使用睡眠系统调用的情况下实现用户空间模式之类的东西?
注意:我试图理解Linux 内核的睡眠系统调用,但说实话我不明白那里发生了什么。我还搜索了 NOP 汇编代码,结果发现它并不是真的什么都不做做,而是做了一些无用的事情(比如 xchg eax、eax),也许这就是 100% CPU 使用率的原因。但我不确定。
究竟有哪些睡眠系统调用的汇编代码是我们无法在用户空间模式下执行的?是不是类似 HLT 的东西
我还尝试HLT在代码中使用汇编,如下所示:
section .text
global _start
_start:
hlt
halter:
jmp _start
section .data
msg db 'Hello world',0xa
len equ $ - msg
Run Code Online (Sandbox Code Playgroud)
但运行此代码后,我看到内核一般保护错误如下:
[15499.991751] traps: hello[22512] general protection fault ip:401000 sp:7ffda4e83980 error:0 in hello[401000+1000]
Run Code Online (Sandbox Code Playgroud)
不知道是不是和保护环有关,或者是我的代码错误?这里的另一个问题是操作系统是否在系统HLT调用下使用或其他受保护的汇编命令 …
根据这个问题,学习系统编程的一个好方法是实现现有的工具。我决定尝试重写ls和ps.
我的问题是如何获得此类文件?
我在哪里可以找到查询内核、文件系统等所需的系统调用 API...
我想也许我可以看看 GNU 工具的源代码。我在哪里可以找到它?
有没有(希望可以在线免费获得)好的文档,你们会推荐从哪里开始?
据我了解,该ls命令调用getdents,它最多返回 x 个目录条目。是否涉及任何其他系统调用?如果我运行ls -l,是否还有更多系统调用?我试图确定是否ls -l比ls.
该getpid系统调用返回调用进程的进程ID。内核如何确定哪个进程正在调用系统调用?
我正在阅读APUE,中断系统调用一章让我感到困惑。
我想根据书中写下我的理解,请指正。
早期 UNIX 系统的一个特点是,如果进程在“慢”系统调用中被阻塞时捕获到信号,则系统调用将被中断。系统调用返回错误并
errno设置为EINTR。这是在假设发生信号并且进程捕获它之后完成的,很有可能发生了一些应该唤醒被阻塞的系统调用的事情。
所以说早期的UNIX 系统有一个特性:如果我的程序使用系统调用,它会被中断/停止,如果程序在任何时候捕捉到信号。(默认处理程序也算作捕获吗?)
例如,如果我有一个read系统调用,它读取 10GB 数据,当它正在读取时,我发送任何一个信号(例如kill -SIGUSR1 pid),然后read将失败并返回。
为了防止应用程序不得不处理中断的系统调用,4.2BSD 引入了某些中断系统调用的自动重启。被自动重新启动的系统调用
ioctl,read,readv,write,writev,wait,和waitpid。正如我们所提到的,这些功能中的前五个功能只有在它们在慢速设备上运行时才会被信号中断;wait并且waitpid在捕获到信号时总是被中断。由于这会导致一些应用程序出现问题,如果操作被中断,则不希望操作重新启动,4.3BSD 允许进程在每个信号的基础上禁用此功能。
所以在引入自动重启之前,我不得不自己处理中断的系统调用。我需要编写如下代码:
中断系统调用的问题在于我们现在必须显式地处理错误返回。典型的代码序列(假设读取操作并假设我们想要重新启动读取,即使它被中断)将是:
again:
if ((n = read(fd, buf, BUFFSIZE)) < 0) {
if (errno == EINTR)
goto again; /* just an interrupted system call */
/* handle other errors …Run Code Online (Sandbox Code Playgroud) 我对操作系统中的系统调用有很大的困惑。根据《操作系统概念第 9 版》一书,(第 63 页)提到:
然而,大多数程序员从未见过这种程度的细节。通常,应用程序开发人员根据应用程序编程接口(API)来设计程序。
在幕后,构成 API 的函数通常代表应用程序程序员调用实际的系统调用。
这意味着,作为程序员,我们不直接使用系统调用。但是,我看到教如何直接使用系统调用的视频,例如这个视频,它访问 read|() 和 write() 系统调用。所以系统调用可以直接使用,也可以使用 API,或者两者都使用??
system-calls ×10
linux-kernel ×3
c ×2
kernel ×2
process ×2
security ×2
architecture ×1
gnu ×1
group ×1
interrupt ×1
linux ×1
ls ×1
signals ×1
sleep ×1