액세스해야하는 파일이 몇 디렉토리에있는 경우 디렉토리를 열고 전에 chroot하고 파일 설명자를 저장하십시오. 그런 다음 소위 * at 함수 (예 : openat(), renameat() 등)를 사용하여 개별 파일을 가져올 수 있습니다. 기본적으로 파일 을 chrooted 디렉토리가 아니라 이미 열려있는 디렉토리 파일 설명자로 여는 것입니다.
안전한 지 여부는 질문이 있지만 Linux에서 작동해야합니다.
편집 : 이것은보기에 좋지 않지만 작동하는 것 같습니다. 내가 가진 것보다 더 많은 취약점을 발견해야합니다. 나는 특권을 없애는 것이 어떻게 영향을 미칠지 시험하지 않았다. 테스트하려면
#include <iostream>
#include <string>
using namespace std;
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
cerr << "USAGE: " << argv[0] << " <jail directory> <freeworld directory> <filename>\n";
exit(EXIT_FAILURE);
}
const string JAILDIR(argv[1]);
const string FREEDIR(argv[2]);
string freefilename(argv[3]);
while (freefilename[0] == '/')
freefilename.erase(0, 1);
DIR *pDir;
if ((pDir = opendir(FREEDIR.c_str())) == NULL)
{
perror("Could not open outside dir");
exit(EXIT_FAILURE);
}
int freeFD = dirfd(pDir);
//cd to jail dir
if (chdir(JAILDIR.c_str()) == -1)
{
perror("cd before chroot");
exit(EXIT_FAILURE);
}
//lock in jail
if (chroot(JAILDIR.c_str()) < 0)
{
cerr << "Failed to chroot to " << JAILDIR << " - " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
//
//in jail, won't work
//
string JailFile(FREEDIR);
JailFile += "/";
JailFile += freefilename;
int jailFD;
if ((jailFD = open(JailFile.c_str(), O_RDONLY)) == -1)
{
cout << "as expected, could not open " << JailFile << endl;
perror("exected open fail");
}
else
{
cout << "defying all logic, opened " << JailFile << endl;
exit(EXIT_FAILURE);
}
//
//using this works
//
if ((jailFD = openat(freeFD, freefilename.c_str(), O_RDONLY)) == -1)
{
cout << "example did not work. Could not open " << freefilename << " Sorry!" << endl;
exit(EXIT_FAILURE);
}
else
cout << "opened " << freefilename << " from inside jail" << endl;
char buff[255];
ssize_t numread;
while (1)
{
if ((numread = read(jailFD, buff, sizeof(buff) - 1)) == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (numread == 0)
break;
buff[numread] = '\0';
cout << buff << endl;
}
return 0;
}
:
에코에 "Hello World">/tmp를/mystuff에.DAT
에서 mkdir/tmp를/감옥
sudo는 ./myprog/tmp를/감옥/tmp 디렉토리는
당신이 chroot 환경에서뿐만 아니라 파일을 복사 할 수 없습니다 mystuff.dat? – fabrizioM
아니요, 너무 많아서 사용자가 보지 않아야하며 다른 프로그램에서 업데이트합니다. – ValenceElectron