实现了myshell, mysu

This commit is contained in:
lzy
2024-05-15 22:02:37 +08:00
parent 7d08b75eaa
commit 0ee62429a2
3 changed files with 177 additions and 11 deletions

View File

@@ -1057,6 +1057,61 @@ int execvp(const char *file, char *const argv[]);
## 用户权限及组权限 ## 用户权限及组权限
`u+s`:如果文件是可执行的,则执行文件时,是以文件的拥有者的权限执行的。
```bash
-rwsr-xr-x 1 root root 68248 Mar 23 2023 /usr/bin/passwd
```
所以普通用户执行`passwd`时,是以`root`的权限执行的。
`g+s`:如果文件是可执行的,则执行文件时,是以文件的所在组的权限执行的。
`uid`和`gid`都有三种类型:
1. `real uid`:进程的实际所有者
2. `effective uid`:进程的有效所有者
3. `saved uid`:进程的保存的有效所有者
```
shell获取身份的流程
fork exec fork
init -->--> getty -->--> login -->--> shell
exec exec
root root root user
```
```c
// 获取当前用户的real uid
uid_t getuid(void);
// 获取当前用户的effective uid
uid_t geteuid(void);
// 获取当前进程的real gid
pid_t getegid(void);
// 获取当前进程的effective gid
pid_t getgid(void);
// 设置当前进程的real uid
int setuid(uid_t uid);
// 设置当前进程的effective uid
int seteuid(uid_t uid);
// 设置当前进程的real gid
int setgid(gid_t gid);
// 设置当前进程的effective gid
int setegid(gid_t gid);
// 交换uid和gid (原子操作)
int setreuid(uid_t ruid, uid_t euid);
// 交换gid和egid (原子操作)
int setregid(gid_t rgid, gid_t egid);
```
## 观摩课:解释器文件 ## 观摩课:解释器文件

View File

@@ -1,38 +1,95 @@
#include <glob.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#define DELIMS " \t\n"
struct cmd_st
{
glob_t globres;
};
static void prompt(void)
{
printf("mysh-0.1$ ");
}
/**
* @brief 解析命令行
* @details
* line 不加 const 是考虑以后可能加 alias 功能
*
* @param line
* @param res
*/
static void parse(char *line, struct cmd_st *res)
{
char *tok;
int i = 0;
//* 根据分隔符分割小串
// strtok();
while (1)
{
tok = strsep(&line, DELIMS);
if (NULL == tok)
break;
if ('\0' == tok[0]) // 判断是否为空串
continue;
// 用glob nocheck 来解析
// 用 i 来让第一次不追加
glob(tok, GLOB_NOCHECK | GLOB_APPEND * i, NULL, &res->globres);
i = 1;
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char *linebuf = NULL;
size_t linebuf_size = 0;
struct cmd_st cmd;
pid_t pid;
while (1) while (1)
{ {
prompt(); prompt();
getline(); if (getline(&linebuf, &linebuf_size, stdin) < 0)
break;
parse(); parse(linebuf, &cmd);
if () if (0)
{ {
; /* dosomething */
} }
else // 外部命令 else // 外部命令
{ {
fork(); pid = fork();
if (< 0) if (pid < 0)
{ {
; perror("fork");
exit(1);
} }
if (0 ==) // child if (0 == pid) // child
{ {
execXX; execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv);
perror(); perror("execvp");
exit(1); exit(1);
} }
else // parent else // parent
{ {
wait(); wait(NULL);
} }
} }
} }

View File

@@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
/**
* @brief 实现一个简单的su命令
* @details
* Usage: mysu uid
*
* @param argc
* @param argv
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 3)
{
fprintf(stderr, "Usage: mysu uid");
exit(1);
}
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if (0 == pid)
{
// child process
setuid(atoi(argv[1]));
execvp(argv[2], argv + 2);
perror("execvp");
exit(1);
}
else // parent process
wait(NULL);
exit(0);
}
/**
* !!!
* 此时,执行./mysu 0 cat /etc/shadow 依旧没有权限
* su - 切换到 root 用户
* 通过
* chown root mysu && chmod u+s mysu 即可
* 再回到普通用户,执行./mysu 0 cat /etc/shadow 即可查看 shadow 文件
*/