在C语言中如何通过fork+exec启动bash并解决终端接管及权限报错问题?
问题解决
1. 初始版本bash无法接管前台的问题
你原来的代码核心问题有两个:
- fork后父进程直接退出,新启动的bash变成孤儿进程被init接管,默认在后台运行
- 你没有把当前终端的前台进程组权限交给新的bash进程
不需要内核模块,用户态完全可以解决,修改逻辑如下:
- 父进程fork后调用
waitpid()阻塞等待子bash进程退出,不要直接返回 - 子进程执行
execl前先调用tcsetpgrp(STDIN_FILENO, getpid())获取终端前台控制权
2. 更新后代码的报错问题
setpgid报错
你调用setpgid(0,0)前没有创建新会话,进程还属于原来父shell的会话组,无法直接修改进程组归属,需要先执行以下操作:
- 调用
signal(SIGTTOU, SIG_IGN)忽略SIGTTOU信号,否则操作终端前台进程组时会触发信号导致进程停止 - 先调用
setsid()创建新会话,让当前进程成为会话首进程,之后再执行setpgid和tcsetpgrp操作
非root用户下setuid、chdir报错
你要切换到其他用户身份、修改终端所有者、进入其他用户的home目录,都需要root权限才能操作,你需要给编译后的可执行文件设置suid root权限:
chown root:root 你的可执行文件名 chmod u+s 你的可执行文件名
注意:设置suid root后程序会以root身份启动,你必须做好密码校验逻辑避免权限泄露。你现有代码里setgid放在setuid前面的顺序是对的,没有root权限这两个调用必然失败。
3. /dev/chardev写入无权限问题
文件系统层面的0666权限只控制文件系统调用的准入,你遇到的权限报错大概率是字符设备驱动内部做了权限校验,比如write接口里判断当前进程的uid是不是root,即使你文件权限开了0666也会被驱动拦截。你需要修改字符设备驱动代码,去掉uid校验逻辑,或者调整校验规则允许目标用户写入。
内容的提问来源于stack exchange,提问作者Ori
相关产品推荐
相关产品推荐

