6974df39a7
Closes #635 newuidmap and newgidmap currently take an integner pid as the first argument, determining the process id on which to act. Accept also "fd:N", where N must be an open file descriptor to the /proc/pid directory for the process to act upon. This way, if you exec 10</proc/99 newuidmap fd:10 100000 0 65536 and pid 99 dies and a new process happens to take pid 99 before newuidmap happens to do its work, then since newuidmap will use openat() using fd 10, it won't change the mapping for the new process. Example: // terminal 1: serge@jerom ~/src/nsexec$ ./nsexec -W -s 0 -S 0 -U about to unshare with 10000000 Press any key to exec (I am 129176) // terminal 2: serge@jerom ~/src/shadow$ exec 10</proc/129176 serge@jerom ~/src/shadow$ sudo chown root src/newuidmap src/newgidmap serge@jerom ~/src/shadow$ sudo chmod u+s src/newuidmap serge@jerom ~/src/shadow$ sudo chmod u+s src/newgidmap serge@jerom ~/src/shadow$ ./src/newuidmap fd:10 0 100000 10 serge@jerom ~/src/shadow$ ./src/newgidmap fd:10 0 100000 10 // Terminal 1: uid=0(root) gid=0(root) groups=0(root) Signed-off-by: Serge Hallyn <serge@hallyn.com>
83 lines
1.7 KiB
C
83 lines
1.7 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2009 , Nicolas François
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#ident "$Id$"
|
|
|
|
#include "prototypes.h"
|
|
#include "defines.h"
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
int get_pid (const char *pidstr, pid_t *pid)
|
|
{
|
|
long long int val;
|
|
char *endptr;
|
|
|
|
errno = 0;
|
|
val = strtoll (pidstr, &endptr, 10);
|
|
if ( ('\0' == *pidstr)
|
|
|| ('\0' != *endptr)
|
|
|| (ERANGE == errno)
|
|
|| (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) {
|
|
return 0;
|
|
}
|
|
|
|
*pid = val;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* If use passed in fd:4 as an argument, then return the
|
|
* value '4', the fd to use.
|
|
*/
|
|
int get_pidfd_from_fd(const char *pidfdstr)
|
|
{
|
|
long long int val;
|
|
char *endptr;
|
|
|
|
errno = 0;
|
|
val = strtoll (pidfdstr, &endptr, 10);
|
|
if ( ('\0' == *pidfdstr)
|
|
|| ('\0' != *endptr)
|
|
|| (ERANGE == errno)
|
|
|| (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) {
|
|
return 0;
|
|
}
|
|
|
|
return (int)val;
|
|
}
|
|
|
|
int open_pidfd(const char *pidstr)
|
|
{
|
|
int proc_dir_fd;
|
|
int written;
|
|
char proc_dir_name[32];
|
|
pid_t target;
|
|
|
|
if (get_pid(pidstr, &target) == 0)
|
|
return -ENOENT;
|
|
|
|
/* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
|
|
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
|
|
target);
|
|
if ((written <= 0) || ((size_t)written >= sizeof(proc_dir_name))) {
|
|
fprintf(stderr, "snprintf of proc path failed for %u: %s\n",
|
|
target, strerror(errno));
|
|
return -EINVAL;
|
|
}
|
|
|
|
proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
|
|
if (proc_dir_fd < 0) {
|
|
fprintf(stderr, _("Could not open proc directory for target %u: %s\n"),
|
|
target, strerror(errno));
|
|
return -EINVAL;
|
|
}
|
|
return proc_dir_fd;
|
|
}
|