X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Frpm-fake.c;h=b3b641a9436c94f88e2bed380ace2d5c3c19a1cd;hb=9ccad609b7d342fd70d95720a98d1a2f073297e9;hp=d15ba628cd2d787e49a972ad2ebe1ef6ec1f8a33;hpb=1e8a9a8192dd2746ff3696e3d8140f2afcf51e7e;p=util-vserver.git diff --git a/util-vserver/src/rpm-fake.c b/util-vserver/src/rpm-fake.c index d15ba62..b3b641a 100644 --- a/util-vserver/src/rpm-fake.c +++ b/util-vserver/src/rpm-fake.c @@ -21,11 +21,11 @@ #endif #include "pathconfig.h" -#include "sys_clone.h" #include "util.h" -#include "lib/vserver.h" -#include "lib/internal.h" +#include +#include +#include #include #include @@ -50,11 +50,22 @@ #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 +#undef _POSIX_SOURCE +#include "capability-compat.h" + #ifndef CLONE_NEWNS # define CLONE_NEWNS 0x00020000 #endif @@ -65,11 +76,13 @@ #define INIT(FILE,FUNC) FUNC##_func = ((__typeof__(FUNC) *) (xdlsym(FILE, #FUNC))) #define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0 +#define DEBUG 1 #define DBG_INIT 0x0001 #define DBG_VARIABLES 0x0002 #define DBG_RESOLVER 0x0004 #define DBG_EXECV 0x0008 +#define DBG_ENV 0x0010 #define DBG_VERBOSE0 0x8000 #define DBG_VERBOSE1 (0x4000 | DBG_VERBOSE0) #define DBG_VERBOSE2 (0x2000 | DBG_VERBOSE1) @@ -87,7 +100,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); @@ -155,17 +169,72 @@ showVersion() exit(0); } +static void +unsetPreloadEnv() +{ + char *env = getenv("LD_PRELOAD"); + char *pos; + + // the const <-> non-const assignment is not an issue since the following + // modifying operations will not be executed in the const-case + env = env ? env : ""; + pos = strstr(env, LIBNAME); + + if (pos!=0) { + char *end_pos = pos + sizeof(LIBNAME); + bool is_end = (end_pos[-1]=='\0'); + char *start_pos; + + end_pos[-1] = '\0'; + start_pos = strrchr(env, ':'); + if (start_pos==0) start_pos = env; + else if (!is_end) ++start_pos; + + if (is_end) *start_pos = '\0'; + else memmove(start_pos, end_pos, strlen(end_pos)+1); + } + +#ifdef DEBUG + if (isDbgLevel(DBG_VERBOSE1|DBG_VARIABLES)) { + WRITE_MSG(2, "env='"); + WRITE_STR(2, env); + WRITE_MSG(2, "'\n"); + } +#endif + + if (*env=='\0') unsetenv("LD_PRELOAD"); +} + +static void +clearEnv() +{ + if (isDbgLevel(DBG_ENV)) WRITE_MSG(2, "clearEnv()\n"); + + unsetenv("RPM_FAKE_S_CONTEXT_REV"); + unsetenv("RPM_FAKE_S_CONTEXT_NR"); + unsetenv("RPM_FAKE_CTX"); + unsetenv("RPM_FAKE_FLAGS"); + unsetenv("RPM_FAKE_CHROOT"); + unsetenv("RPM_FAKE_NAMESPACE_MOUNTS"); + + unsetenv("RPM_FAKE_RESOLVER_GID"); + unsetenv("RPM_FAKE_RESOLVER_UID"); + unsetenv("RPM_FAKE_RESOLVER"); + unsetenv("RPM_FAKE_PWSOCKET"); + + unsetenv("RPM_FAKE_DEBUG"); + + unsetPreloadEnv(); +} + static int -getAndClearEnv(char const *key, int dflt) +getDefaultEnv(char const *key, int dflt) { char *env = getenv(key); int res; if (env==0 || env[0]=='\0') res = dflt; - else { - res = atoi(env); - unsetenv(key); - } + else res = atoi(env); return res; } @@ -180,7 +249,7 @@ setupContext(xid_t xid, char const **xid_str) xid_t rc=VC_NOCTX; if ((xid==VC_DYNAMIC_XID || !vc_is_dynamic_xid(xid)) && - (rc=vc_create_context(xid))==VC_NOCTX && + (rc=vc_ctx_create(xid))==VC_NOCTX && errno!=EEXIST) { perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); exit(255); @@ -195,9 +264,9 @@ setupContext(xid_t xid, char const **xid_str) 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.ccaps = 0ull; caps.cmask = ~0ull; - caps.bcaps = ~vc_get_securecaps(); + caps.bcaps = ~vc_get_insecurebcaps(); caps.bmask = ~0ull; Evc_set_ccaps(rc, &caps); @@ -244,7 +313,6 @@ initPwSocket() exit(255); } } - unsetenv("RPM_FAKE_PWSOCKET"); } #else static void @@ -278,10 +346,14 @@ initPwSocket() } if (pid==0) { - char const *args[15]; + 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]; + + clearEnv(); setsid(); dup2(res_sock[1], 0); @@ -294,11 +366,18 @@ 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; - if (root) { *ptr++ = "-r"; *ptr++ = root; } + *ptr++ = "-F"; *ptr++ = flag_str; + *ptr++ = "-C"; *ptr++ = caps_str; + if (root) { *ptr++ = "-r"; *ptr++ = "."; } if (uid) { *ptr++ = "-u"; *ptr++ = uid; } if (gid) { *ptr++ = "-g"; *ptr++ = gid; } + if (root) Echdir(root); + if (setupContext(ctx, &xid_str)) { *ptr++ = "-s"; } else if (xid_str) { *ptr++ = "-c"; *ptr++ = xid_str; } @@ -329,15 +408,35 @@ initPwSocket() exit(255); } } - - unsetenv("RPM_FAKE_RESOLVER_GID"); - unsetenv("RPM_FAKE_RESOLVER_UID"); - unsetenv("RPM_FAKE_RESOLVER"); } } #endif static void +reduceCapabilities() +{ + struct __user_cap_header_struct header; + struct __user_cap_data_struct user; + + header.version = _LINUX_CAPABILITY_VERSION; + header.pid = 0; + + if (capget(&header, &user)==-1) { + perror("capget()"); + exit(wrapper_exit_code); + } + + user.effective &= ~(1< non-const assignment is not an issue since the following - // modifying operations will not be executed in the const-case - env = env ? env : ""; - pos = strstr(env, LIBNAME); - - if (pos!=0) { - char *end_pos = pos + sizeof(LIBNAME); - bool is_end = (end_pos[-1]=='\0'); - char *start_pos; - - end_pos[-1] = '\0'; - start_pos = strrchr(env, ':'); - if (start_pos==0) start_pos = env; - else if (!is_end) ++start_pos; - - if (is_end) *start_pos = '\0'; - else memmove(start_pos, end_pos, strlen(end_pos)+1); - } - -#ifdef DEBUG - if (isDbgLevel(DBG_VERBOSE1|DBG_VARIABLES)) { - WRITE_MSG(2, "env='"); - WRITE_STR(2, env); - WRITE_MSG(2, "'\n"); - } -#endif - - if (*env=='\0') unsetenv("LD_PRELOAD"); -} - void initRPMFake() { if (getenv("RPM_FAKE_VERSION")) showVersion(); if (getenv("RPM_FAKE_HELP")) showHelp(); - debug_level = getAndClearEnv("RPM_FAKE_DEBUG", 0); + debug_level = getDefaultEnv("RPM_FAKE_DEBUG", 0); if (isDbgLevel(DBG_INIT)) WRITE_MSG(2, ">>>>> initRPMFake <<<<<\n"); - fixPreloadEnv(); + reduceCapabilities(); initSymbols(); initEnvironment(); initPwSocket(); @@ -525,17 +591,24 @@ 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 (vc_isSupported(vcFEATURE_MIGRATE)) - res = vc_migrate_context(ctx); - else + 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 + } + + clearEnv(); + if (res!=-1) - res=execv_func(path, argv); + res=execve(path, argv, envp); return res; } @@ -544,6 +617,7 @@ struct ExecvParams { char const * path; char * const * argv; + char * const * envp; char const * mnts; }; @@ -566,13 +640,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; @@ -581,6 +656,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 @@ -613,7 +689,29 @@ removeNamespaceMounts(char const *path, char * const argv[]) int -execv(char const *path, char * const argv[]) __THROW +execv(char const *path, char * const argv[]) { - return removeNamespaceMounts(path, argv); + extern char **environ; + + if (isDbgLevel(DBG_EXECV)) { + WRITE_MSG(2, "execv('"); + WRITE_STR(2, path); + WRITE_MSG(2, "', ...)\n"); + } + + return removeNamespaceMounts(path, argv, environ); +} + +int +rpm_execcon(unsigned int UNUSED verified, + const char *filename, + char *const argv[], char *const envp[]) +{ + if (isDbgLevel(DBG_EXECV)) { + WRITE_MSG(2, "rpm_execcon(..., '"); + WRITE_STR(2, filename); + WRITE_MSG(2, "', ...)\n"); + } + + return removeNamespaceMounts(filename, argv, envp); }