《linux 内核完全剖析》 sys.c 代码分析

2024-06-06 10:08

本文主要是介绍《linux 内核完全剖析》 sys.c 代码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 sys.c 代码分析

 

 

setregid

/** This is done BSD-style, with no consideration of the saved gid, except* that if you set the effective gid, it sets the saved gid too.  This* makes it possible for a setgid program to completely drop its privileges,* which is often a useful assertion to make when you are doing a security* audit over a program.** The general idea is that a program which uses just setregid() will be* 100% compatible with BSD.  A program which uses just setgid() will be* 100% compatible with POSIX w/ Saved ID's.*/
int sys_setregid(int rgid, int egid)//设置real group ID ,effective group ID
{if (rgid>0) {if ((current->gid == rgid) ||suser())//如果当前进程的gid == real group ID 或者拥有超级用户权限,就可以把当前进程的group ID更改为 real Group ID current->gid = rgid;else //否则setregid是不允许的,返回错误值return(-EPERM);}if (egid>0) {if ((current->gid == egid) ||//如果当前进程的gid 或者effective gid 等于egid 或者拥有超级用户权限,则可以修改当前进程的egid和sgid(current->egid == egid) ||suser()) {current->egid = egid;current->sgid = egid;} elsereturn(-EPERM);}return 0;
}


setgid

/** setgid() is implemeneted like SysV w/ SAVED_IDS*/
int sys_setgid(int gid) //设置当前进程的group ID
{if (suser()) //有超级用户权限就可以更改当前进程的gid,egid(effective gid) ,sgid(saved gid)都设置为gidcurrent->gid = current->egid = current->sgid = gid;else if ((gid == current->gid) || (gid == current->sgid))//如果当前进程的sgid 或者gid(current) 等于 gid(传入参数) ,那么把当前进程的effective gid 设置为gidcurrent->egid = gid;elsereturn -EPERM;return 0;
}



 

sys_time

int sys_time(long * tloc) //设置系统时间
{int i;i = CURRENT_TIME;if (tloc) {verify_area(tloc,4);put_fs_long(i,(unsigned long *)tloc);}return i;
}


sys_setreuid

/** Unprivileged users may change the real user id to the effective uid* or vice versa.  (BSD-style)** When you set the effective uid, it sets the saved uid too.  This* makes it possible for a setuid program to completely drop its privileges,* which is often a useful assertion to make when you are doing a security* audit over a program.** The general idea is that a program which uses just setreuid() will be* 100% compatible with BSD.  A program which uses just setuid() will be* 100% compatible with POSIX w/ Saved ID's.*/
int sys_setreuid(int ruid, int euid) //uid == user ID 设置real 和 effective user ID
{int old_ruid = current->uid;if (ruid>0) {if ((current->euid==ruid) ||(old_ruid == ruid) ||suser())current->uid = ruid;elsereturn(-EPERM);}if (euid>0) {if ((old_ruid == euid) ||(current->euid == euid) ||suser()) {current->euid = euid;current->suid = euid;} else {current->uid = old_ruid;return(-EPERM);}}return 0;
}

setuid()


/** setuid() is implemeneted like SysV w/ SAVED_IDS** Note that SAVED_ID's is deficient in that a setuid root program* like sendmail, for example, cannot set its uid to be a normal* user and then switch back, because if you're root, setuid() sets* the saved uid too.  If you don't like this, blame the bright people* in the POSIX commmittee and/or USG.  Note that the BSD-style setreuid()* will allow a root program to temporarily drop privileges and be able to* regain them by swapping the real and effective uid.  */
int sys_setuid(int uid) //设置user ID
{if (suser())current->uid = current->euid = current->suid = uid;else if ((uid == current->uid) || (uid == current->suid))current->euid = uid;elsereturn -EPERM;return(0);
}int sys_stime(long * tptr) //设置系统时间
{if (!suser())return -EPERM;startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;jiffies_offset = 0;return 0;
}

sys_times

int sys_times(struct tms * tbuf) //获取系统时间把内核数据段的数据读到tbuf里去
{if (tbuf) {verify_area(tbuf,sizeof *tbuf);put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);}return jiffies;
}

sys_brk

int sys_brk(unsigned long end_data_seg) //brk 数据段结尾
{if (end_data_seg >= current->end_code &&//如果end_data_seg大于当前进程的代码段结尾并且小于当前进程的(堆栈-16K),于是//把end_date_seg作为新的数据段结尾end_data_seg < current->start_stack - 16384)current->brk = end_data_seg;return current->brk;
}


sys_setpgid

/** This needs some heave checking ...* I just haven't get the stomach for it. I also don't fully* understand sessions/pgrp etc. Let somebody who does explain it.** OK, I think I have the protection semantics right.... this is really* only important on a multi-user system anyway, to make sure one user* can't send a signal to a process owned by another.  -TYT, 12/12/91*/
int sys_setpgid(int pid, int pgid)  
{int i;if (!pid)pid = current->pid;if (!pgid)pgid = current->pid;if (pgid < 0)return -EINVAL;for (i=0 ; i<NR_TASKS ; i++)if (task[i] && (task[i]->pid == pid) &&((task[i]->p_pptr == current) ||(task[i] == current))) {if (task[i]->leader)return -EPERM;if ((task[i]->session != current->session) ||((pgid != pid) &&(session_of_pgrp(pgid) != current->session)))return -EPERM;task[i]->pgrp = pgid;return 0;}return -ESRCH;
}


 getpgrp

int sys_getpgrp(void) //获得当前进程的pgrp == process group
{return current->pgrp;
}

setsid

int sys_setsid(void) //设置session ID
{if (current->leader && !suser()) //当前进程不是session leader或者拥有超级权限的话是无法更改session ID的return -EPERM;current->leader = 1; //当前进程被确认为session leadercurrent->session = current->pgrp = current->pid;current->tty = -1;return current->pgrp;
}


getgroups

/** Supplementary group ID's*/
int sys_getgroups(int gidsetsize, gid_t *grouplist)
//这里应该有问题,一个进程不可能属于多一个进程组
//原因很简单,一个进程的group id只能是一个值!这就约束了它就只能属于一个进程组!他的group leader只能有一个!
{int    i;if (gidsetsize)verify_area(grouplist, sizeof(gid_t) * gidsetsize);for (i = 0; (i < NGROUPS) && (current->groups[i] != NOGROUP);i++, grouplist++) {if (gidsetsize) {if (i >= gidsetsize)return -EINVAL;put_fs_word(current->groups[i], (short *) grouplist);}}return(i);
}

uname

static struct utsname thisname = {UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, UTS_MACHINE
};int sys_uname(struct utsname * name) //获取系统名称信息
{int i;if (!name) return -ERROR;verify_area(name,sizeof *name);for(i=0;i<sizeof *name;i++)put_fs_byte(((char *) &thisname)[i],i+(char *) name);return 0;
}

sethostname

/** Only sethostname; gethostname can be implemented by calling uname()*/
int sys_sethostname(char *name, int len) //设置系统名词信息
{int    i;if (!suser())return -EPERM;if (len > MAXHOSTNAMELEN)return -EINVAL;for (i=0; i < len; i++) {if ((thisname.nodename[i] = get_fs_byte(name+i)) == 0)break;}if (thisname.nodename[i]) {thisname.nodename[i>MAXHOSTNAMELEN ? MAXHOSTNAMELEN : i] = 0;}return 0;
}

getrlimit


int sys_getrlimit(int resource, struct rlimit *rlim) //获取当前进程的资源界限值
{if (resource >= RLIM_NLIMITS)return -EINVAL;verify_area(rlim,sizeof *rlim);put_fs_long(current->rlim[resource].rlim_cur,(unsigned long *) rlim);put_fs_long(current->rlim[resource].rlim_max,((unsigned long *) rlim)+1);return 0;    
}

setrlimit


int sys_setrlimit(int resource, struct rlimit *rlim)
{struct rlimit new, *old;if (resource >= RLIM_NLIMITS)return -EINVAL;old = current->rlim + resource;new.rlim_cur = get_fs_long((unsigned long *) rlim);new.rlim_max = get_fs_long(((unsigned long *) rlim)+1);if (((new.rlim_cur > old->rlim_max) ||(new.rlim_max > old->rlim_max)) &&!suser())return -EPERM;*old = new;return 0;
}

umask

int sys_umask(int mask)//当设置当前进程创建文件的属性
{int old = current->umask;current->umask = mask & 0777;return (old);
}












 



这篇关于《linux 内核完全剖析》 sys.c 代码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035806

相关文章

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意