#endif
#include "pathconfig.h"
+#include "sys_clone.h"
#include "util.h"
-#include <vserver.h>
+#include "lib/vserver.h"
+#include "lib/internal.h"
+#include <sys/socket.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
+#define ENSC_WRAPPERS_PREFIX "rpm-fake.so: "
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include <wrappers.h>
+
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
#define PLATFORM_FILE "/etc/rpm/platform"
#define INIT(FILE,FUNC) FUNC##_func = ((__typeof__(FUNC) *) (xdlsym(FILE, #FUNC)))
-#define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0
+#define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0
#define DBG_INIT 0x0001
#define DBG_VERBOSE1 (0x4000 | DBG_VERBOSE0)
#define DBG_VERBOSE2 (0x2000 | DBG_VERBOSE1)
-static char const * ctx_s = 0;
-static ctx_t ctx = VC_NOCTX;
+int wrapper_exit_code = 255;
+
+static xid_t ctx = VC_NOCTX;
static uint32_t caps = ~0;
static int flags = 0;
static char const * mnts = 0;
return res;
}
+ /// \returns true iff we are in ctx after leaving this function
+static bool
+setupContext(xid_t xid, char const **xid_str)
+{
+ bool res = false;
+
+ if (vc_isSupported(vcFEATURE_MIGRATE)) {
+ xid_t rc=VC_NOCTX;
+
+ if ((xid==VC_DYNAMIC_XID || !vc_is_dynamic_xid(xid)) &&
+ (rc=vc_ctx_create(xid))==VC_NOCTX &&
+ errno!=EEXIST) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_create_context()");
+ exit(255);
+ }
+
+ if (rc!=VC_NOCTX) {
+ char buf[sizeof(xid_t)*3 + 128];
+ size_t l;
+ struct vc_ctx_caps caps;
+
+ strcpy(buf, "rpm-fake.so #");
+ l = utilvserver_fmt_uint(buf+sizeof("rpm-fake.so #")-1, getppid());
+ Evc_set_vhi_name(rc, vcVHI_CONTEXT, buf, sizeof("rpm-fake.so #")+l-1);
+
+ caps.ccaps = 0ull;
+ caps.cmask = ~0ull;
+ caps.bcaps = ~vc_get_insecurebcaps();
+ caps.bmask = ~0ull;
+ Evc_set_ccaps(rc, &caps);
+
+ // context will be activated later...
+
+ xid = rc;
+ res = true;
+ }
+ }
+
+ if (xid==VC_DYNAMIC_XID)
+ *xid_str = 0;
+ else {
+ char buf[sizeof(xid_t)*3 + 2];
+ size_t l;
+
+ l = utilvserver_fmt_uint(buf, xid); buf[l] = '\0';
+ *xid_str = strdup(buf);
+ }
+
+ Ewrite(3, &xid, sizeof xid);
+ return res;
+}
+
#if 0
static void
initPwSocket()
connect(pw_sock, (struct sockaddr *)(&addr), sizeof addr)==-1 ||
(flag=fcntl(pw_sock, F_GETFD))==-1 ||
fcntl(pw_sock, F_SETFD, flag | FD_CLOEXEC)==-1) {
- perror("error while initializing pw-socket");
+ perror(ENSC_WRAPPERS_PREFIX "error while initializing pw-socket");
exit(255);
}
}
pipe(sync_pipe)==-1 ||
fcntl(res_sock[0], F_SETFD, FD_CLOEXEC)==-1 ||
fcntl(sync_pipe[0], F_SETFD, FD_CLOEXEC)==-1) {
- perror("rpm-fake.so: failed to create/initialize resolver-socket or pipe");
+ perror(ENSC_WRAPPERS_PREFIX "failed to create/initialize resolver-socket or pipe");
exit(255);
}
pid = fork();
if (pid==-1) {
- perror("rpm-fake.so: fork()");
+ perror(ENSC_WRAPPERS_PREFIX "fork()");
exit(255);
}
if (pid==0) {
- char const *args[10];
+ char const *args[20];
char const **ptr = args;
char const *env[] = { "HOME=/", "PATH=/bin:/usr/bin", 0 };
+ char const *xid_str;
+ char flag_str[ sizeof(flags)*3 + 2];
+ char caps_str[ sizeof(caps)*3 + 2];
setsid();
dup2(res_sock[1], 0);
dup2(res_sock[1], 1);
- dup2(sync_pipe[1], 2);
- close(sync_pipe[1]);
+ if (sync_pipe[1]!=3) {
+ close(3);
+ dup2(sync_pipe[1], 3);
+ close(sync_pipe[1]);
+ }
close(res_sock[1]);
/* ... *socket[0] are marked as close-on-exec ...*/
+ flag_str[utilvserver_fmt_uint(flag_str, flags)] = '\0';
+ caps_str[utilvserver_fmt_uint(caps_str, caps)] = '\0';
+
*ptr++ = resolver;
+ *ptr++ = "-F"; *ptr++ = flag_str;
+ *ptr++ = "-C"; *ptr++ = caps_str;
if (root) { *ptr++ = "-r"; *ptr++ = root; }
if (uid) { *ptr++ = "-u"; *ptr++ = uid; }
if (gid) { *ptr++ = "-g"; *ptr++ = gid; }
- if (ctx_s) { *ptr++ = "-c"; *ptr++ = ctx_s; }
- *ptr++ = 0;
+
+ if (setupContext(ctx, &xid_str)) { *ptr++ = "-s"; }
+ else if (xid_str) { *ptr++ = "-c"; *ptr++ = xid_str; }
+ *ptr++ = 0;
execve(resolver, (char **)args, (char **)env);
- perror("rpm-fake.so: failed to exec resolver");
+ perror(ENSC_WRAPPERS_PREFIX "failed to exec resolver");
exit(255);
}
else {
pw_sock = res_sock[0];
sync_sock = sync_pipe[0];
- if (read(sync_sock, &c, 1)!=1 ||
+ if (read(sync_sock, &ctx, sizeof ctx)!=sizeof(ctx) ||
+ read(sync_sock, &c, 1)!=1 ||
write(pw_sock, ".", 1)!=1 ||
read(pw_sock, &c, 1)!=1 ||
c!='.') {
- WRITE_MSG(2, "rpm-fake.so: failed to initialize communication with resolver");
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "failed to initialize communication with resolver\n");
+ exit(255);
+ }
+
+ if (wait4(pid, 0, WNOHANG,0)==-1) {
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX" unexpected initialization-error of resolver\n");
exit(255);
}
}
- free((char *)ctx_s);
unsetenv("RPM_FAKE_RESOLVER_GID");
unsetenv("RPM_FAKE_RESOLVER_UID");
unsetenv("RPM_FAKE_RESOLVER");
}
#endif
- ctx_s = getenv("RPM_FAKE_CTX");
- if (ctx_s) ctx_s = strdup(ctx_s);
-
- ctx = getAndClearEnv("RPM_FAKE_CTX", VC_RANDCTX);
+ ctx = getAndClearEnv("RPM_FAKE_CTX", VC_DYNAMIC_XID);
caps = getAndClearEnv("RPM_FAKE_CAP", ~0x3404040f);
flags = getAndClearEnv("RPM_FAKE_FLAGS", 0);
root = getenv("RPM_FAKE_CHROOT");
mnts = getenv("RPM_FAKE_NAMESPACE_MOUNTS");
- if (mnts!=0) mnts = strdup(mnts);
+ if (mnts && *mnts) mnts = strdup(mnts);
+ else mnts = 0;
unsetenv("RPM_FAKE_CHROOT");
unsetenv("RPM_FAKE_NAMESPACE_MOUNTS");
void
exitRPMFake()
{
- write(2, ">>>>> exitRPMFake <<<<<\n", 24);
+ if (isDbgLevel(DBG_INIT)) WRITE_MSG(2, ">>>>> exitRPMFake <<<<<\n");
if (pw_sock!=-1) {
uint8_t c;
read(sync_sock, &c, 1);
static int
execvWorker(char const *path, char * const argv[])
{
- int res;
+ int res = -1;
- if ((res=vc_new_s_context(ctx,caps,flags))!=-1 &&
- (res=execv_func(path, argv)!=-1) ) {}
+ if (vc_isSupported(vcFEATURE_MIGRATE))
+ res = vc_ctx_migrate(ctx);
+ else
+#ifdef VC_ENABLE_API_COMPAT
+ res = vc_new_s_context(ctx,caps,flags);
+#else
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not change context: migrate kernel feature missing and 'compat' API disabled\n");
+#endif
+
+ if (res!=-1)
+ res=execv_func(path, argv);
return res;
}
// make wait4() working...
signal(SIGCHLD, SIG_DFL);
- pid = syscall(__NR_clone, CLONE_NEWNS|SIGCHLD|CLONE_VFORK, 0);
+#ifdef NDEBUG
+ pid = sys_clone(CLONE_NEWNS|SIGCHLD|CLONE_VFORK, 0);
+#else
+ pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0);
+#endif
switch (pid) {
case -1 : return -1;