5 #include "cvmfs_config.h"
12 #include <sys/mount.h>
23 #define CLONE_NEWUSER 0x10000000
26 #define CLONE_NEWPID 0x20000000
33 #define CVMFS_HAS_UNSHARE 1
34 #ifdef __GLIBC_MINOR__
35 #if __GLIBC_MINOR__ < 4
36 #undef CVMFS_HAS_UNSHARE
48 int fd = open(
"/proc/sys/kernel/unprivileged_userns_clone", O_RDONLY);
61 #ifdef CVMFS_HAS_UNSHARE
68 std::string uid_map =
StringifyInt(map_uid_to) +
" " + uid_str +
" 1";
69 std::string gid_map =
StringifyInt(map_gid_to) +
" " + gid_str +
" 1";
73 fd = open(
"/proc/self/setgroups", O_WRONLY);
75 nbytes = write(fd,
"deny", 4);
79 fd = open(
"/proc/self/uid_map", O_WRONLY);
81 nbytes = write(fd, uid_map.data(), uid_map.length());
83 if (nbytes != static_cast<ssize_t>(uid_map.length()))
86 fd = open(
"/proc/self/gid_map", O_WRONLY);
88 nbytes = write(fd, gid_map.data(), gid_map.length());
90 if (nbytes != static_cast<ssize_t>(gid_map.length()))
100 bool BindMount(
const std::string &from,
const std::string &to) {
104 int rvi = mount(from.c_str(), to.c_str(),
"", MS_BIND |
MS_REC, NULL);
114 int rvi = mount(
"proc", to.c_str(),
"proc", 0, NULL);
121 #ifdef CVMFS_HAS_UNSHARE
124 int rvi = unshare(CLONE_NEWNS);
125 if (rvi != 0)
return false;
127 rvi = chdir(cwd.c_str());
135 #ifdef CVMFS_HAS_UNSHARE
138 static void Reaper(
int , siginfo_t * ,
void * ) {
140 pid_t retval = waitpid(-1, NULL, WNOHANG);
156 #ifdef CVMFS_HAS_UNSHARE
158 if (rvi != 0)
return false;
176 max_fd =
static_cast<int>(sysconf(_SC_OPEN_MAX));
177 for (
int fd = 0; fd < max_fd; fd++) {
178 if (fd != pipe_parent[1])
182 pid_t parent_pid = getpid();
183 SafeWrite(pipe_parent[1], &parent_pid,
sizeof(parent_pid));
184 SafeWrite(pipe_parent[1], &pid,
sizeof(pid));
186 rvi = waitpid(pid, &status, 0);
188 if (WIFEXITED(status))
189 exit(WEXITSTATUS(status));
193 close(pipe_parent[1]);
194 if (fd_parent != NULL)
195 *fd_parent = pipe_parent[0];
200 memset(&sa, 0,
sizeof(sa));
202 sa.sa_flags = SA_SIGINFO;
203 sigfillset(&sa.sa_mask);
204 rvi = sigaction(SIGCHLD, &sa, NULL);
207 rvi = mount(
"",
"/proc",
"proc", 0, NULL);
bool CreateMountNamespace()
const int kNsFeatureUserAvailable
const int kNsFeatureMount
const int kNsFeatureUserEnabled
bool SafeWrite(int fd, const void *buf, size_t nbyte)
assert((mem||(size==0))&&"Out Of Memory")
void MakePipe(int pipe_fd[2])
bool SymlinkExists(const std::string &path)
ssize_t SafeRead(int fd, void *buf, size_t nbyte)
static void Reaper(int, siginfo_t *, void *)
NamespaceFailures CreateUserNamespace(uid_t map_uid_to, gid_t map_gid_to)
bool ProcMount(const std::string &to)
string StringifyInt(const int64_t value)
int CheckNamespaceFeatures()
bool CreatePidNamespace(int *fd_parent)
bool BindMount(const std::string &from, const std::string &to)
std::string GetCurrentWorkingDirectory()