X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Frpm-fake.c;h=f6c9770a5577deab53236113882e62cded837b80;hb=245184e3863bc621fd6a318fa51da348c1ef86d9;hp=c9e4d7299458e7f472c27b17e30d09fc3586df15;hpb=44c84cff90ca76559278b8316a2dd65743ae8db9;p=util-vserver.git diff --git a/util-vserver/src/rpm-fake.c b/util-vserver/src/rpm-fake.c index c9e4d72..f6c9770 100644 --- a/util-vserver/src/rpm-fake.c +++ b/util-vserver/src/rpm-fake.c @@ -22,10 +22,12 @@ #include "pathconfig.h" #include "util.h" -#include "sys_clone.h" -#include +#include +#include +#include +#include #include #include #include @@ -43,12 +45,24 @@ #include #include #include -#include #include #include #include #include + + // from selinux.h + // FIXME: add configure autodetection and include directly +int rpm_execcon(unsigned int verified, + const char *filename, + char *const argv[], char *const envp[]); + + +#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 @@ -57,7 +71,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 @@ -68,7 +82,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; @@ -80,7 +95,8 @@ static unsigned int debug_level = 0; static bool is_initialized = false; -DECLARE(execv); + //DECLARE(rpm_execcon); + //DECLARE(execv); DECLARE(getpwnam); DECLARE(getgrnam); DECLARE(endpwent); @@ -163,6 +179,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_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() @@ -181,7 +249,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); } } @@ -208,20 +276,23 @@ 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[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); @@ -234,15 +305,22 @@ initPwSocket() 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 { @@ -253,21 +331,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"); @@ -295,11 +373,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"); @@ -317,7 +391,8 @@ initEnvironment() static void initSymbols() { - INIT(RTLD_NEXT, execv); + //INIT(RTLD_NEXT, rpm_execcon); + //INIT(RTLD_NEXT, execv); INIT(RTLD_NEXT, getgrnam); INIT(RTLD_NEXT, getpwnam); INIT(RTLD_NEXT, endpwent); @@ -467,12 +542,21 @@ endpwent() static int -execvWorker(char const *path, char * const argv[]) +execvWorker(char const *path, char * const argv[], char * const envp[]) { - 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=execve(path, argv, envp); return res; } @@ -481,6 +565,7 @@ struct ExecvParams { char const * path; char * const * argv; + char * const * envp; char const * mnts; }; @@ -503,13 +588,14 @@ removeNamespaceMountsChild(struct ExecvParams const *params) ptr = strtok(0, ":"); } - return execvWorker(params->path, params->argv); + return execvWorker(params->path, params->argv, params->envp); } static int -removeNamespaceMounts(char const *path, char * const argv[]) +removeNamespaceMounts(char const *path, + char * const argv[], char * const envp[]) { - if (mnts==0) return execvWorker(path, argv); + if (mnts==0) return execvWorker(path, argv, envp); { int status; @@ -518,6 +604,7 @@ removeNamespaceMounts(char const *path, char * const argv[]) params.path = path; params.argv = argv; + params.envp = envp; params.mnts = mnts; // the rpmlib signal-handler is still active; use the default one to @@ -550,7 +637,17 @@ removeNamespaceMounts(char const *path, char * const argv[]) int -execv(char const *path, char * const argv[]) __THROW +execv(char const *path, char * const argv[]) +{ + extern char **environ; + + return removeNamespaceMounts(path, argv, environ); +} + +int +rpm_execcon(unsigned int UNUSED verified, + const char *filename, + char *const argv[], char *const envp[]) { - return removeNamespaceMounts(path, argv); + return removeNamespaceMounts(filename, argv, envp); }