我有一个C++程序,运行在嵌入式Linux系统上,程序由用户'myuser'启动,并使用'uid'管理权限。
该程序由用户'myuser'启动,并使用'uid'来管理权限。
ls -l /bin/myprog
-rwsr-sr-x 1 root root 757328 May 7 12:55 myprog
我写了一个小类来处理id。它在程序启动时读取所有的id,并在运行时根据需要的权限提升改变euid和egid。
/*************************************************************
* HEADER FILE
*************************************************************/
#ifndef _PRIVILEGE_H
#define _PRIVILEGE_H
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
class CPrivilege
{
private:
uid_t _ruid;
uid_t _euid;
uid_t _suid;
gid_t _rgid;
gid_t _egid;
gid_t _sgid;
int _status;
int getPrivilege(uid_t&,uid_t&,uid_t&,gid_t&,gid_t&,gid_t&);
public :
CPrivilege();
int elevate();
int down();
int print();
int status();
};
#endif
/*************************************************************
* CPP FILE
*************************************************************/
#include "_privilege.h"
CPrivilege::CPrivilege()
{
_status = getPrivilege(_ruid,_euid,_suid,_rgid,_egid,_sgid);
}
int CPrivilege::status()
{
return _status;
}
int CPrivilege::getPrivilege(uid_t& ruid, uid_t& euid, uid_t& suid, gid_t& rgid, gid_t& egid, gid_t& sgid)
{
if (getresuid(&ruid, &euid, &suid) == -1) {
printf("getresuid error\n");
return EXIT_FAILURE;
}
if (getresgid(&rgid, &egid, &sgid) == -1) {
printf("getresgid error\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int CPrivilege::elevate()
{
/* Switch to target user. effective uid gets the saved uid. */
if (seteuid((uid_t)_suid) == -1) {
printf("seteuid error\n");
return (_status = EXIT_FAILURE);
}
/* Switch to target group. effective gid gets the saved gid. */
if (setegid((gid_t)_sgid) == -1) {
printf("setegid error\n");
return (_status = EXIT_FAILURE);
}
return (_status = EXIT_SUCCESS);
}
int CPrivilege::down()
{
/* Switch to target user. effective uid gets the real uid. */
if (seteuid((uid_t)_ruid) == -1) {
printf("seteuid error\n");
return (_status = EXIT_FAILURE);
}
/* Switch to target group. effective gid gets the real gid. */
if (setegid((gid_t)_rgid) == -1) {
printf("setegid error\n");
return (_status = EXIT_FAILURE);
}
return (_status = EXIT_SUCCESS);
}
int CPrivilege::print()
{
uid_t ruid;
uid_t euid;
uid_t suid;
gid_t rgid;
gid_t egid;
gid_t sgid;
printf("status = %d\n", _status);
getPrivilege(ruid,euid,suid,rgid,egid,sgid);
printf("ruid = %d, euid = %d, suid = %d\n", ruid, euid, suid);
printf("rgid = %d, egid = %d, sgid = %d\n", rgid, egid, sgid);
}
另外,这里有一个主程序,它打开一个shell脚本,然后运行它。
/*************************************************************
* MAIN FILE
*************************************************************/
#include "_privilege.h"
#include <string>
int main(int argc, char *argv[])
{
CPrivilege priv;
priv.down();
priv.print();
// [...) Program stuff with user privilege
std::string system_cmd;
int ret;
system_cmd = "/root/test_script";
priv.elevate();
priv.print();
FILE *pf;
pf = fopen(system_cmd.c_str(),"r");
if (pf != NULL)
{
printf("Root privilege\n\n");
fclose(pf);
}
else
printf("User privilege\n\n");
system(system_cmd.c_str());
priv.down();
priv.print();
// [...) Other Program stuff with user privilege
return 0;
}
/*************************************************************
* SHELL FILE
*************************************************************/
#!/bin/sh
echo 'HELLO WORLD !'
当我以 "root "启动我的程序时,脚本被启动,我的输出如下。
status = 0
ruid = 0, euid = 0, suid = 0
rgid = 0, egid = 0, sgid = 0
status = 0
ruid = 0, euid = 0, suid = 0
rgid = 0, egid = 0, sgid = 0
Root privilege
HELLO WORLD !
status = 0
ruid = 0, euid = 0, suid = 0
rgid = 0, egid = 0, sgid = 0
当我用myuser启动我的程序时,我可以打开脚本文件,即使它在 "root "文件夹中。但我无法启动脚本,并得到 "Permission denied "的回答。
status = 0
ruid = 1009, euid = 1009, suid = 0
rgid = 1013, egid = 1013, sgid = 0
status = 0
ruid = 1009, euid = 0, suid = 0
rgid = 1013, egid = 0, sgid = 0
Root privilege
sh: /root/test_script: Permission denied
status = 0
ruid = 1009, euid = 1009, suid = 0
rgid = 1013, egid = 1013, sgid = 0
我应该怎么做才能用root权限调用脚本?
来自Bash手册:
如果启动shell时有效用户(组)id不等于真实用户(组)id, 并且没有提供-p选项, [...] 并且有效用户id被设置为真实用户id. 如果在调用时提供了-p选项,则启动行为与之相同,但有效用户id不会被重置。
请参阅 实施 对不起,非官方链接)。
我想你需要更改uid以及有效uid,或者将你的命令改为 bash -p /root/test_script
.