#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include "compat.h"
+
+#include <vserver.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
-#include <asm/unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
+#ifndef CLONE_NEWNS
+# define CLONE_NEWNS 0x00020000
+#endif
+
#define LIBNAME "rpm-fake.so"
#define PLATFORM_FILE "/etc/rpm/platform"
-#define INIT(FILE,FUNC) FUNC##_func = dlsym(FILE, #FUNC)
+#define INIT(FILE,FUNC) FUNC##_func = ((__typeof__(FUNC) *) (dlsym(FILE, #FUNC)))
#define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0
static bool is_initialized = false;
DECLARE(execv);
//DECLARE(open);
-static int def_NR_new_s_context = 259;
-#undef __NR_new_s_context
-static int __NR_new_s_context_rev0;
-static int __NR_new_s_context_rev1;
-
-static int new_s_context_rev0(int, int, int);
-static int new_s_context_rev1(int, int *, int, int);
-
-_syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags)
-_syscall4(int, new_s_context_rev1, int, nbctx, int *, ctxs, int, remove_cap, int, flags)
-
-static int
-new_s_context(int rev,
- int nbctx, int *ctxs, int remove_cap, int flags)
-{
- int ret;
-
- switch (rev) {
- case 0 :
- {
- int ctx;
-
- switch (nbctx) {
- case 0 : ctx = -1; break;
- case 1 : ctx = ctxs[0]; break;
- default : errno = EINVAL; return -1;
- }
-
- ret = new_s_context_rev0(ctx, remove_cap, flags);
-
- break;
- }
-
- case 1 :
- ret = new_s_context_rev1(nbctx, ctxs, remove_cap, flags);
- break;
-
- default :
- errno = EINVAL; return -1;
- }
-
- return ret;
-}
-
-static void
-initVserverSyscalls(int s_context_NR)
-{
- int nr = (s_context_NR!=-1) ? s_context_NR : def_NR_new_s_context;
-
- __NR_new_s_context_rev0 = __NR_new_s_context_rev1 = nr;
-}
-
static int
getAndClearEnv(char const *key, int dflt)
{
- char *env = getenv(key);
+ char *env = getenv(key);
int res;
if (env==0 || env[0]=='\0') res = dflt;
{
if (is_initialized) return;
- initVserverSyscalls(getAndClearEnv("RPM_FAKE_S_CONTEXT_NR", -1));
+#ifdef VC_ENABLE_API_LEGACY
+ {
+ extern void vc_init_internal_legacy(int ctx_rev, int ctx_number,
+ int ipv4_rev, int ipv4_number);
+
+ vc_init_internal_legacy(getAndClearEnv("RPM_FAKE_S_CONTEXT_REV", 0),
+ getAndClearEnv("RPM_FAKE_S_CONTEXT_NR", 280),
+ 3, 281);
+ }
+#else
+ (void)getAndClearEnv("RPM_FAKE_S_CONTEXT_REV", 0);
+ (void)getAndClearEnv("RPM_FAKE_S_CONTEXT_NR", 280);
+#endif
INIT(RTLD_NEXT, execv);
//INIT(RTLD_NEXT, open);
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;
int res;
int ctx;
- printf("+execvWorker\n");
ctx = getAndClearEnv("RPM_FAKE_CTX", -1);
- if ( (res=new_s_context(getAndClearEnv("RPM_FAKE_S_CONTEXT_REV", 0),
- ctx==-1 ? 0 : 1,
- &ctx,
- getAndClearEnv("RPM_FAKE_CAP", ~0x3404040f),
- getAndClearEnv("RPM_FAKE_FLAGS", 0)))!=-1 &&
+ if ( (res=vc_new_s_context(ctx,
+ getAndClearEnv("RPM_FAKE_CAP", ~0x3404040f),
+ getAndClearEnv("RPM_FAKE_FLAGS", 0)))!=-1 &&
(res=execv_func(path, argv)!=-1) ) {}
- printf("-execvWorker -> res=%u, err=%s\n",res,strerror(errno));
return res;
}
strcpy(buf, params->mnts);
ptr = strtok(buf, ":");
while (ptr) {
- system("cat /proc/mounts");
- system("pstree -h");
- system("ls -l /proc/self/ /proc/self/fd/ /var/lib /var/lib/rpm/");
- if (umount2(ptr, 0)==-1) { dprintf(2, "ptr='%s' -> ", ptr); perror("umount2()"); return -1; }
+ if (umount2(ptr, 0)==-1) {
+ // FIXME: What is the semantic for CLONE_NEWNS? Is it ok that mounts in
+ // chroots are visible only, when chroot is on /dev/root?
+ //
+ // For now, ignore any errors, but future versions should handle them.
+
+ //return -1;
+ }
ptr = strtok(0, ":");
}
{
char const * mnts = getenv("RPM_FAKE_NAMESPACE_MOUNTS");
- printf("mnts='%s'\n", mnts);
if (mnts==0) return execvWorker(path, argv);
{
- printf("l=%u\n", __LINE__);
- char buf[512 + 2*strlen(mnts)];
- int status;
- pid_t p;
- struct ExecvParams params = {
- .path = path,
- .argv = argv,
- .mnts = mnts,
- };
-
- printf("l=%u\n", __LINE__);
-
-
- system("mount -t proc none /proc");
- system("cat /proc/mounts");
- //system("pstree -h");
- system("ls -l /proc/self/ /proc/self/fd/ /var/lib /var/lib/rpm/");
- pid_t pid = clone(removeNamespaceMountsChild, buf+sizeof(buf)/2,
- CLONE_NEWNS|SIGCHLD|CLONE_VFORK, ¶ms);
-
- printf("l=%u\n", __LINE__);
+ char buf[512 + 2*strlen(mnts)];
+ int status;
+ pid_t p, pid;
+ struct ExecvParams params;
+
+ params.path = path;
+ params.argv = argv;
+ params.mnts = mnts;
+
+ // the rpmlib signal-handler is still active; use the default one to
+ // make wait4() working...
+ signal(SIGCHLD, SIG_DFL);
+
+ pid = clone(removeNamespaceMountsChild, buf+sizeof(buf)/2,
+ CLONE_NEWNS|SIGCHLD|CLONE_VFORK, ¶ms);
+
if (pid==-1) return -1;
- while ((p=waitpid(pid, &status, 0))==-1 &&
+ while ((p=wait4(pid, &status, 0,0))==-1 &&
(errno==EINTR || errno==EAGAIN)) ;
- if (p==-1) return -1;
- printf("removeNamespaceMountsChild() -> status=%u\n", status);
+ if (p==-1) return -1;
if (WIFEXITED(status)) exit(WEXITSTATUS(status));
if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status));