X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Frpm-fake.c;h=2c1310639fca46623a44620571a6fc0a1646ed94;hb=5b39edfee423f5f3cbe8fa223dcfdc9e8d66e286;hp=b2f416cd3491c01e604a4cbf472be6541b8fd868;hpb=ae53d976e97aafa6640133059a4bc5fec069a393;p=util-vserver.git diff --git a/util-vserver/src/rpm-fake.c b/util-vserver/src/rpm-fake.c index b2f416c..2c13106 100644 --- a/util-vserver/src/rpm-fake.c +++ b/util-vserver/src/rpm-fake.c @@ -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); @@ -108,10 +122,10 @@ xdlsym(void *handle, const char *symbol) void *res = dlsym(handle, symbol); if (res==0) { char const *error = dlerror(); - write(2, symbol, strlen(symbol)); - write(2, ": ", 2); - write(2, error, strlen(error)); - write(2, "\n", 2); + Vwrite(2, symbol, strlen(symbol)); + Vwrite(2, ": ", 2); + Vwrite(2, error, strlen(error)); + Vwrite(2, "\n", 2); _exit(255); } @@ -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; } @@ -244,7 +313,6 @@ initPwSocket() exit(255); } } - unsetenv("RPM_FAKE_PWSOCKET"); } #else static void @@ -284,6 +352,8 @@ initPwSocket() 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); @@ -302,10 +372,12 @@ initPwSocket() *ptr++ = resolver; *ptr++ = "-F"; *ptr++ = flag_str; *ptr++ = "-C"; *ptr++ = caps_str; - if (root) { *ptr++ = "-r"; *ptr++ = root; } + 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; } @@ -336,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(); @@ -453,8 +512,8 @@ exitRPMFake() if (isDbgLevel(DBG_INIT)) WRITE_MSG(2, ">>>>> exitRPMFake <<<<<\n"); if (pw_sock!=-1) { uint8_t c; - read(sync_sock, &c, 1); - write(pw_sock, "Q", 1); + if (read(sync_sock, &c, 1)!=1) { /*...*/ } + if (write(pw_sock, "Q", 1)!=1) { /*...*/ } } } @@ -469,16 +528,13 @@ doPwStringRequest(uint32_t *result, char style, char const *name) uint8_t code; uint8_t c; - // read the token... - read(sync_sock, &c, 1); - - write(pw_sock, &style, 1); - write(pw_sock, &len, sizeof len); - write(pw_sock, name, len); - read (pw_sock, &code, sizeof code); - read (pw_sock, result, sizeof *result); - - return code!=0; + return (TEMP_FAILURE_RETRY(read (sync_sock, &c, 1))==1 && + TEMP_FAILURE_RETRY(write(pw_sock, &style, 1))==1 && + TEMP_FAILURE_RETRY(write(pw_sock, &len, sizeof len))==sizeof(len) && + TEMP_FAILURE_RETRY(write(pw_sock, name, len))==(ssize_t)(len) && + TEMP_FAILURE_RETRY(read (pw_sock, &code, sizeof code))==sizeof(code) && + TEMP_FAILURE_RETRY(read (pw_sock, result, sizeof *result))==sizeof(*result) && + code!=0); } struct passwd * @@ -486,6 +542,7 @@ getpwnam(const char * name) { if (pw_sock==-1) return getpwnam_func(name); else { + uint32_t id; static struct passwd res = { .pw_passwd = "*", .pw_gid = -1, @@ -495,7 +552,8 @@ getpwnam(const char * name) }; res.pw_name = (char *)(name); - if (!doPwStringRequest(&res.pw_uid, 'P', name)) return 0; + if (!doPwStringRequest(&id, 'P', name)) return 0; + res.pw_uid = id; return &res; } @@ -506,13 +564,15 @@ getgrnam(const char * name) { if (pw_sock==-1) return getgrnam_func(name); else { + uint32_t id; static struct group res = { .gr_passwd = "*", .gr_mem = 0 }; res.gr_name = (char *)(name); - if (!doPwStringRequest(&res.gr_gid, 'G', name)) return 0; + if (!doPwStringRequest(&id, 'G', name)) return 0; + res.gr_gid = id; return &res; } @@ -522,31 +582,36 @@ void endgrent() { if (pw_sock==-1) endgrent_func(); + TEMP_FAILURE_RETRY(write(pw_sock, "Cg", 2)); } void endpwent() { if (pw_sock==-1) endpwent_func(); + TEMP_FAILURE_RETRY(write(pw_sock, "Cp", 2)); } static int -execvWorker(char const *path, char * const argv[]) +execvWorker(char const *path, char * const argv[], char * const envp[]) { int res = -1; if (vc_isSupported(vcFEATURE_MIGRATE)) res = vc_ctx_migrate(ctx); - else + 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; } @@ -555,6 +620,7 @@ struct ExecvParams { char const * path; char * const * argv; + char * const * envp; char const * mnts; }; @@ -577,13 +643,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; @@ -592,6 +659,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 @@ -626,5 +694,33 @@ removeNamespaceMounts(char const *path, char * const argv[]) int 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); +} + +int +is_selinux_enabled() +{ + return 0; }