X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Frpm-fake.c;h=9160d3984b43337f214705e5194d5e512f5ca3e7;hb=7fdb31f6a9475c02a5e56e3a83c22f37ede24792;hp=5728535f53a76e1bff6d762b8c703bf45e3571ab;hpb=5535bc9f97a07db1094a7a72cd13d16f7385b020;p=util-vserver.git diff --git a/util-vserver/src/rpm-fake.c b/util-vserver/src/rpm-fake.c index 5728535..9160d39 100644 --- a/util-vserver/src/rpm-fake.c +++ b/util-vserver/src/rpm-fake.c @@ -21,10 +21,13 @@ #endif #include "pathconfig.h" +#include "sys_clone.h" #include "util.h" -#include +#include "lib/vserver.h" +#include "lib/internal.h" +#include #include #include #include @@ -42,12 +45,16 @@ #include #include #include -#include #include #include #include #include +#define ENSC_WRAPPERS_PREFIX "rpm-fake.so: " +#define ENSC_WRAPPERS_VSERVER 1 +#define ENSC_WRAPPERS_UNISTD 1 +#include + #ifndef CLONE_NEWNS # define CLONE_NEWNS 0x00020000 #endif @@ -56,7 +63,7 @@ #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 @@ -67,7 +74,8 @@ #define DBG_VERBOSE1 (0x4000 | DBG_VERBOSE0) #define DBG_VERBOSE2 (0x2000 | DBG_VERBOSE1) -static char const * ctx_s = 0; +int wrapper_exit_code = 255; + static xid_t ctx = VC_NOCTX; static uint32_t caps = ~0; static int flags = 0; @@ -162,6 +170,58 @@ getAndClearEnv(char const *key, int dflt) 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_insecurecaps(); + 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() @@ -180,7 +240,7 @@ 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); } } @@ -207,20 +267,21 @@ initPwSocket() 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[15]; char const **ptr = args; char const *env[] = { "HOME=/", "PATH=/bin:/usr/bin", 0 }; + char const *xid_str; setsid(); dup2(res_sock[1], 0); @@ -237,11 +298,13 @@ initPwSocket() 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 { @@ -252,21 +315,21 @@ initPwSocket() 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\n"); + 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, "rpm-fake.so: unexpected initialization-error of resolver\n"); + 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"); @@ -294,11 +357,7 @@ initEnvironment() } #endif - ctx_s = getenv("RPM_FAKE_CTX"); - if (ctx_s && *ctx_s) ctx_s = strdup(ctx_s); - else ctx_s = 0; - - 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"); @@ -468,10 +527,19 @@ endpwent() 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; } @@ -523,7 +591,11 @@ removeNamespaceMounts(char const *path, char * const argv[]) // 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;