diff --git a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md index d38c883..35fb37e 100644 --- a/C13-Linux系统编程/C13-Linux系统编程学习笔记.md +++ b/C13-Linux系统编程/C13-Linux系统编程学习笔记.md @@ -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); + +``` ## 观摩课:解释器文件 diff --git a/C13-Linux系统编程/process_basic/myshell.c b/C13-Linux系统编程/process_basic/myshell.c index 87a79fb..28618e9 100644 --- a/C13-Linux系统编程/process_basic/myshell.c +++ b/C13-Linux系统编程/process_basic/myshell.c @@ -1,38 +1,95 @@ +#include #include #include +#include +#include +#include +#include #include +#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) { + char *linebuf = NULL; + size_t linebuf_size = 0; + struct cmd_st cmd; + pid_t pid; + while (1) { prompt(); - getline(); + if (getline(&linebuf, &linebuf_size, stdin) < 0) + break; - parse(); + parse(linebuf, &cmd); - if (内部命令) + if (0) { - ; + /* dosomething */ } else // 外部命令 { - fork(); - if (< 0) + pid = fork(); + if (pid < 0) { - ; + perror("fork"); + exit(1); } - if (0 ==) // child + if (0 == pid) // child { - execXX; - perror(); + execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv); + perror("execvp"); exit(1); } else // parent { - wait(); + wait(NULL); } } } diff --git a/C13-Linux系统编程/process_basic/mysu.c b/C13-Linux系统编程/process_basic/mysu.c new file mode 100644 index 0000000..ccdacc9 --- /dev/null +++ b/C13-Linux系统编程/process_basic/mysu.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +/** + * @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 文件 + */ \ No newline at end of file