操作系统实验一:Linux进程管理及其扩展

news2024/10/17 8:32:29
  • 实验目的:

通过实验,加深理解进程控制块、进程队列等概念,了解进程管理的具体实施方法。

  • 实验内容:

1. 阅读并分析Linux内核源代码,了解进程控制块、进程队列等数据结构;

2. 实现一个系统调用,使得可以根据指定的参数隐藏进程,使用户无法使用ps或top观察到进程状态。具体要求如下:

(1)实现系统调用int hide(pid_t pid, int on),在进程pid有效的前提下,如果on置1,进程被隐藏,用户无法通过ps或top观察到进程状态;如果on置0且此前为隐藏状态,则恢复正常状态。

(2)考虑权限问题,只有根用户才能隐藏进程。

(3)设计一个新的系统调用int hide_user_processes(uid_t uid, char *binname),参数uid为用户ID号,当binname参数为NULL时,隐藏该用户的所有进程;否则,隐藏二进制映像名为binname的用户进程。该系统调用应与hide系统调用共存。

(4)在/proc目录下创建一个文件/proc/hidden,该文件可读可写,对应一个全局变量hidden_flag,当hidden_flag为0时,所有进程都无法隐藏,即便此前进程被hide系统调用要求隐藏。只有当hidden_flag为1时,此前通过hide调用要求被屏蔽的进程才隐藏起来。

(5)在/proc目录下创建一个文件/proc/hidden_process,该文件的内容包含所有被隐藏进程的pid,各pid之间用空格分开。

  • 实验步骤:

(1)新增系统调用 hide 并且(2)考虑权限问题

设计思路和流程图:

  1. 在 include/linux/sched.h 中修改 task_struct,添加成员 cloak,0 表示进程显示,1 表示进程隐藏:

  1. 在进程创建时,将task_struct的成员cloak初始化为未隐藏。fork系统调用的实现代码在kernel/fork.c中,具体实现的主要函数为do_fork,do_fork中调用copy_process函数创建子进程,建议将初始化cloak的代码添加在copy_process函数中:
  1. 打开文件 arch/i386/kernel/syscall_table.S,新增系统调用的名称:
  1. 在 include/linux 目录下新建 hide.h 头文件:
  2. 在 kernel 目录下新建 hide.c 文件:
  3. 修改 kernel/Makefile,添加 hide.o,使得 hide.c 在编译时可见:
  4. 找到文件 include/asm-i386/unistd.h,加上 hide 系统调用号的宏定义:
  5. 修改 include/linux/syscalls.h。添加 sys_hide 的声明
  6. 修改 fs/proc/base.c 中的 proc_pid_readdir 函数以及proc_pid_lookup 函数,当 cloak=1 时隐藏,当 cloak=0 时不隐藏:

主要数据结构及其说明:

使用 task_struct,通过 hide.c 中 on 对结构体中 cloak 的赋值,改变进程

的状态。

源程序并附上注释(关键部分):

1. hide.c 程序

首先进行判断,只有 root 用户才可以进行操作。通过使用 find_task_by_pid 获取给定进程 pid 的结构体 task_struct。

进行判断,如果参数 on=1 则隐藏该进程;如果 on=0 则显示该进程。

在隐藏操作之后通过函数 proc_flush_task 清空缓存,接触现有的 dentry

项。

  1. 测试程序:

用户通过输入 uid 选择需要隐藏的进程;通过输入 status 设置 on 值,on=0

显示进程,on=1 隐藏进程。

#include<stdio.h>

#include<sys/syscall.h>

#include<unistd.h>

int main()

{

/*

 * user input first number as uid

*/

    int pid_input=0;

    printf("Please input the pid: \n");

    scanf("%d",&pid_input);

    int syscallNum=321;//hide

    pid_t pid=pid_input;

/*

 * user input second number as on(status)

*/

    int status=0;

    printf("Please input the on status: (1->the process hidden;0->the process shown)\n");

    scanf("%d",&status);

    int on=status;//hidden/shown

    syscall(syscallNum,pid,on);

    return 0;

}

程序运行结果及分析:

首先使用 ps aux 指令查看所有进程:

尝试在用户态隐藏进程 76:

用户可以根据自身需求通过输入 pid 隐藏进程,同时可以根据需求设置on值选择隐藏或是显示某进程,再通过 ps aux 查看进程:

可以看到76号进程依然显示。这是因为考虑权限问题,只有 root 用户可以通过 hide 隐藏进程。

下面进入 root 再次重复上面的操作:

可以看到在 root 态,通过调用 hide 函数隐藏76号进程可以实现将该进程隐藏。

下面通过将 on 值设置为 0 恢复 76号进程的显示:

可以看到通过调用 hide 函数,选择进程76并将 on 值设置为 0,恢复了

进程76号的显示。

(3) 新增系统调用 hide_user_processes

设计思路和流程图:

1. 打开文件 arch/i386/kernel/syscall_table.S,新增系统调用的名称。

2. 在 include/linux 目录下新建 hide_user_processes.h 头文件

3. 在 kernel 目录下新建 hide_user_processes.c 文件

4.修改 kernel/Makefile,添加 hide_user_processes.o 使得hide_user_processes.c 在编译时可见

5. 找到文件 include/asm-i386/unistd.h,加上 hide_user_processes 系统调

用号的宏定义:

6. 修改 include/linux/syscalls.h。添加 sys_hide_user_processes 的声明

主要数据结构及其说明:

通过改变结构体中 cloak 的值,控制进程的隐藏/显示状态。

源程序并附上注释(关键部分):

hide_user_processes.c

首先进入判断:如果参show_all=0,则隐藏相应进程;如果 show_all=1且当前为 root,则显示所有进程,即置所有进程cloak=0。

判断只有 root 用户才能隐藏相应进程。

当 binname=NULL 时,隐藏所有给定 uid 的进程,即将该 uid 所有进程 cloak

置为 1.当binname为给定值时,只隐藏该进程。:

#include<linux/linkage.h>

#include<linux/types.h>

#include<linux/sched.h>

#include<linux/pid.h>

#include<linux/proc_fs.h>

#include<linux/string.h>

asmlinkage int sys_hide_user_processes(uid_t uid,char *binname,int show_all)

{

/*

 * if binname == NULL,hide all processes of given uid

*/

    struct task_struct *p=NULL;

    if(show_all==0)

    {

        if(current->uid==0)//root only

        {

            /*

             * if binname == NULL,hide all processes of given uid

             */

            if(binname==NULL)

            {

                for_each_process(p)

                {

                    if((p->uid)==uid)

                    {

                        p->cloak=1;//hide all processes

                        proc_flush_task(p);

                    }

                }

                printk("All processes of uid %d are hidden. \n",uid);

            }

            else

            {

               /*

                *hide the process of the corresponding name

                */

               for_each_process(p)

               {

                   char *s=p->comm;

                   if(strcmp(s,binname)==0 && p->uid==uid)

                   {

                       p->cloak=1;

                       printk("Process %s of uid %d is hidden. \n",binname,uid);

                       proc_flush_task(p);

                   }

               }

            }

         }

 else//not root

             printk("Permission denied. \n");

    }

    else if(show_all  != 0 && (current->uid)==0)//show all of the processes,hidden or not

    {

        for_each_process(p)

        {

            p->cloak=0;

        }

    }

    return 0;

测试程序:

#include<stdio.h>

#include<stdlib.h>

#include<sys/syscall.h>

#include<unistd.h>

int main()

{

/*

 * 用户输入uid

 *0->root;500->seu

*/

    int uid_input=0;

    printf("Please input the uid: (0->root;500->seu)\n");

    scanf("%d",&uid_input);

    int syscallNum=322;

    uid_t uid=uid_input;

/*

 *用户输入binname,如果binname==NULL所有进程都会被隐藏

*/

    printf("Please input the binname: (NULL->all processes)\n");

    char *binname=(char*)malloc(1024*sizeof(char));

    scanf("%s",binname);

    char *judge="NULL";//to judge ? NULL

    if(strcmp(binname,judge)==0)binname=NULL;//NULL

    int status=0;

/*

 *用户输入status,0->default;1->show all processes

*/

    printf("Please input the recover_status: (0->default;1->show all processes)\n");

    scanf("%d",&status);

    int recovery_status=status;

    syscall(syscallNum,uid,binname,recovery_status);

    free(binname);

    return 0;

}

程序运行结果及分析:

首先使用 ps aux 查看进程

隐藏 seu 的所用进程(即输入 uid=500):

用户可以根据自身需求选择 root(0)或者 seu(500),同时可以根据需

求设置 binname 隐藏某特定进程,同时可以设置 recover_status 选择恢

复进程或者隐藏进程,使用 ps aux 查看进程:

seu的所有进程都被隐藏了。

隐藏 pid=1 的 init 进程(即 binname 输入 init):

查看进程:

pid=1 的进程被隐藏。

通过设置 recover_status=1 恢复已经被隐藏的进程:

查看进程:

被隐藏的进程恢复正常。

隐藏所有 root 进程:

查看进程:

root 进程都已经被隐藏,除了4487和4587两个root 进程。这是因为4487号进程是当前打开的 terminal,而4587号进程即 ps aux 指令是在执行 hide_user_processes 之后执行的指令。所以这两个 root 进程依旧正常显示。

(4) 在/proc 目录下创建一个文件/proc/hidden

设计思路和流程图:

1.设置全局变量 hidden_flag。在 fs/proc 目录下创建 var.h 文件,定义全局变量 hidden_flag,其它文件中需要用到这个全局变量的时候,需使用include包含这个头文件。

2. 实现 hidden 文件的创建和读写

proc 文件系统在初始化函数 proc_root_init 中会调用 proc_misc_init 函

数,此函数用于创建/proc 根目录下的文件,那么将创建 hidden 文件的代码

插入到此函数中就可以在 proc 初始化时得到执行。

添加回调函数。在/fs/proc/proc_misc.c 中 proc_misc_init 函数的最后添

加创建 hidden 文件的代码,并指定其回调函数。

  1. 结合上面根据cloak判断进程,这个实验与之类似,只需在fs/proc/base.c文件中,修改proc_pid_readdir函数以及proc_pid_lookup函数,在cloak判断之前,增加hidden_flag对进程的约束:

主要数据结构及其说明:

通过使用 PCB 和结构体完成 hidden 相应功能。

源程序并附上注释(关键部分):

在 proc_misc.c 中添加回调函数。初始化 hidden_flag=1,BUF_LEN=128。在

函数 proc_read_hidden 中通过 sprintf 函数将 hidden_flag 的值传给 page,

再返回 len 值。

在 proc_write_hidden 函数中通过 copy_from_user 函数将所输入的值传递

给 temp,再从 temp 中得到值传递给 hidden_flag。

创建hidden文件的代码,使用的是create_proc_entry函数,然后指定其回调函数。

struct proc_dir_entry *ptr=create_proc_entry("hidden",0644,NULL);

ptr->read_proc=proc_read_hidden;

ptr->write_proc=proc_write_hidden;

程序运行结果及分析:

首先通过调用 hide_user_process 隐藏进程,查看进程,所有 seu 进程都已经被隐藏:

设置 hidden_flag 值,将 hidden_flag 值设置为 0:

查看进程,发现所有进程都处于显示状态,即无法隐藏:

将 hidden_flag 值设置为 1:

查看进程:

之前被隐藏的 seu 进程又处于隐藏状态。

(5) 在/proc 目录下创建一个文件/proc/hidden_process  

设计思路和流程图:

hidden_process 用于存储所有被隐藏进程的 pid。该文件只需要设计回调函

数即可。

进行判断,只有当 hidden_flag=1 时,才将被隐藏的进程的 pid 写入该文件。

还是上一次的那个proc_misc.c程序

然后重新编译安装内核,重启后测试。

主要数据结构及其说明:

使用了结构体、进程控制块、进程队列等数据结构。

源程序并附上注释(关键部分):

hidden_process 用于存储所有被隐藏进程的 pid。该文件只需要设计回调函

数即可。

进行判断,只有当 hidden_flag=1 时,才将被隐藏的进程的 pid 写入该文件。

程序运行结果及分析:

首先,ps aux,查看当前进程:

通过调用 hide 隐藏 pid=1 的进程:

ps aux查看进程,发现 pid=1 进程已经被隐藏:

通过指令:cd /proc 继而cat hidden_process 查看文件内容,可以发现文件包含所有被隐藏进程的 pid,此处即 pid=1:

恢复 pid=1 进程:

再次查看 hidden_process 文件内容,发现内容为空:

通过 hide_user_processes 隐藏 seu 所有进程:

通过指令 cat hidden_process 查看该文件内容,可以发现该文件包含所

有被隐藏进程的 pid:

恢复所有被隐藏进程:

再次打开 hidden_process:

发现 hidden_process 内容为空,即没有被隐藏的进程。

  • 实验体会:

实验中有一次遇到过这样的问题:

当时百思不得其解,反复检验代码,最后通过对比文件中原有的头文件,终于发下端倪,因为我添加的头文件var.h与该程序在同一级文件夹下,所以不应该使用#include<var.h>而应该是#include”var.h”,果然这样改过之后,就正确的make all了。

在做实验0的时候,在这个地方一直报错,后来在群里看了老师的解答,原来是实验手册出了问题,正确做法不是把头文件加在最开始,而是应该加在其他头文件的后面。这样修改以后,果然不再有问题了。

最开始做的时候,make mrproper一直出现报错,后来发现,在root下做,就不会有问题,原来是权限的问题。

在做的时候,想过使用vim,但是发现系统并没有预装,参照网上教程也一直出现问题:

最后请教老师,但是老师也不知道因为什么,只好不了了之,全程使用vi命令。

还有就是,在最开始做的时候,只知道无脑跟着实验手册,也没有看是否有报错,然后会出现各种稀奇古怪的问题:

后来实在没有办法,就选择重装了一次系统,这一次,认真研究,开动脑筋,这才一步步的把实验做完,通过本次实验,我深刻的认识到,千万不要迷信实验手册,一定要自己着手解决问题才行!

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

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

相关文章

基于springboot留守儿童爱心网站

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的&#xff0c;前后端分离。 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;…

C++核心编程和桌面应用开发 第十一天(静态转换 动态转换 常量转换 重新解释转换)

目录 1.静态类型转换 1.1语法 1.2用法 2.动态类型转换 2.1语法 2.2用法 3.常量类型转换 3.1语法 3.2用法 4.重新解释转换 4.1语法 1.静态类型转换 1.1语法 static_cast<目标转换类型>(待转换变量) 1.2用法 可用于基本数据类型之间的转换。比如int和char之…

Input-Source-Pro:自动切换输入法并提示状态

Input Source Pro 是一款 macOS 上的输入法辅助工具&#xff0c;它可以根据不同应用、不同网站来自动切换输入法&#xff0c;并可以在鼠标周围显示当前输入法状态。 macOS 不像 Windows 那样能保存输入法状态&#xff0c;因此这样的软件还是挺有用的。 ‍ 介绍 官网&#x…

前后端请求一致性学习

在进行前后端分离开发项目的过程中&#xff0c;前后端同学往往需要依照接口文档的基本信息以及相应的响应格式进行接口请求的开发&#xff0c;在这个过程中涉及到常见的Get、Post、Put、Patch等等的请求&#xff0c;相应的前后端的书写格式是什么&#xff0c;这篇文章进行一个记…

keil 配置栈溢出保护(arm)

1.前提是keil 配置为arm-gcc 编译器环境 2.配置编译项加上 -fstack-protector-strong 栈溢出的测试代码: void aaa(int a, char c) { char arr[5]; arr[a] = c; } aaa(8, d);//任意地方调用,超过数组arr的元素 添加代码栈溢出检测: uint32_t __stack_chk_gua…

WhatsApp防死号应该怎么做?

“WhatsApp又死号了”——外贸人的噩梦每天都会上演。号损是小事&#xff0c;重要是是成千上万的客户累计与聊天记录被一扫而空&#xff0c;所以相信我&#xff0c;当你准备好最WhatsApp&#xff0c;那么WhatsApp账号养成的操作从一开始就要注意并且牢记&#xff01;下面给大家…

Golang | Leetcode Golang题解之第482题秘钥格式化

题目&#xff1a; 题解&#xff1a; func licenseKeyFormatting(s string, k int) string {ans : []byte{}for i, cnt : len(s)-1, 0; i > 0; i-- {if s[i] ! - {ans append(ans, byte(unicode.ToUpper(rune(s[i]))))cntif cnt%k 0 {ans append(ans, -)}}}if len(ans) &…

Unity Spine优化思路

最近终于闲下来了&#xff0c;于是开始把近期探索到的unity相关优化整理起来。 我们的项目采用的人物表现方式是spine动画&#xff0c;这在2D游戏里算比较常见的解决方案了&#xff0c;但是里面有一些设置需要提前注意一下&#xff0c;否则会造成不必要的性能浪费。 养成读官…

【实战指南】Vue.js 介绍组件数据绑定路由构建高效前端应用

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

WPF入门_01布局

WPF布局包括两个阶段&#xff1a;一个测量&#xff08;measure&#xff09;阶段和一个排列(arrange)阶段.每个Panel都提供了自己的MeasureOverride和ArrangeOverride方法 1、Canvas 布局控件 Canvas面板是最轻量级的布局容器&#xff0c;它不会自动调整内部元素的排列和大小&…

仿 Mac 个人网站开发 |项目复盘

一、前言 1.1 灵感来源 早年有幸看到国外大佬做的一个 基于 Web 的 Windows XP 桌面娱乐系统, 那时刚好有搭建一个个人博客的想法, 所以就想是否可以基于 WEB 实现一个仿 Mac UI 的个人博客, 以应用的形式来展示博客各个功能! 1.2 相关链接(求个 Star) 前端开源代码后端开源…

计算机网络—vlan(虚拟局域网)

内容补充 冲突域 如果两台设备同时发送数据&#xff0c;他们的数据会互相干扰&#xff0c;那么他们就处于同一冲突域&#xff0c;例如集线器&#xff08;总线型&#xff0c;所有设备共享带宽&#xff09;的所有端口都处于冲突域。 广播域 如果一台设备发送数据&#xff0c;…

怎么为pdf文件设置密码?几种PDF文件设置密码的方法推荐

怎么为pdf文件设置密码&#xff1f;设置PDF文件密码&#xff0c;正是应对这一挑战的有效手段之一。通过为PDF文件设置密码&#xff0c;我们能够为文档加上一道安全锁&#xff0c;确保只有掌握密码的用户才能打开和查看文件内容。这一措施不仅保护了文档的隐私性&#xff0c;还防…

【C++11入门】新特性总结之lambda表达式

现代C语言的核心特征之一&#xff1a;lambda表达式。虽然其它编程语言早已具备了这种特性&#xff0c;但直到C11标准发布&#xff0c;C11才具备了lambda表达式。本节主要讲解lambda表达式的语法和使用方法。具体包括&#xff1a;捕获列表、可选参数列表、可选异常说明符、可选返…

5分钟精通Windows环境变量

科普内容 what why how&#xff08;WWH&#xff09;三步走 1. what&#xff1a;Windows环境变量是什么 Windows环境变量&#xff0c;本质上是告诉了Windows操作系统一堆文件夹路径&#xff0c;如下图 2. why&#xff1a; 创造Windows环境变量的目的 发明Windows环境变量是为了…

多机编队—(3)Fast_planner无人机模型替换为Turtlebot3模型实现无地图的轨迹规划

文章目录 前言一、模型替换二、Riz可视化三、坐标变换四、轨迹规划最后 前言 前段时间已经成功将Fast_planner配置到ubuntu机器人中&#xff0c;这段时间将Fast_planner中的无人机模型替换为了Turtlebot3_waffle模型&#xff0c;机器人识别到环境中的三维障碍物信息&#xff0…

HarmonyOS开发(ArkUI简单使用)

一、开发准备 1.官网 https://developer.huawei.com/consumer/cn/ 2.工具 DevEco Studio 下载&#xff1a; 下载中心 | 华为开发者联盟-HarmonyOS开发者官网&#xff0c;共建鸿蒙生态 3.安装 4.开发组件ArkTs ArkTS是HarmonyOS主力应用开发语言。它在TypeScript&#xf…

分享一个关于产线工控安全的主机加固方案

在数字化时代&#xff0c;数据安全是企业运营的重中之重。勒索病毒作为一种新型的网络攻击手段&#xff0c;已经成为全球范围内企业面临的严峻挑战。最近&#xff0c;一起震惊全球的勒索病毒事件再次敲响了警钟&#xff1a;一家国际航运巨头遭受了勒索软件攻击&#xff0c;导致…

设计模式和软件框架的关系

设计模式和软件框架在软件开发中都有助于解决复杂问题和提高代码质量&#xff0c;但它们在概念和使用上存在一些区别。它们的关系可以通过以下几点理解&#xff1a; 层次与抽象程度 设计模式&#xff08;Design Patterns&#xff09;是一组通用的、可复用的解决方案&#xff0…

Android10 recent键相关总结

目录 初始化流程 点击Recent键流程 RecentsActivity 显示流程 RecentsModel 获取数据管理类 RecentsActivity 布局 已处于Recent界面时 点击recent 空白区域 点击返回键 recent组件配置 Android10 Recent 功能由 System UI&#xff0c;Launcher共同实现。 初始化流程 …