3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <asm/unistd.h>
34 #include <sys/mount.h>
38 #include <sys/types.h>
41 #define LIBNAME "rpm-fake.so"
42 #define PLATFORM_FILE "/etc/rpm/platform"
44 #define INIT(FILE,FUNC) FUNC##_func = dlsym(FILE, #FUNC)
45 #define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0
47 static bool is_initialized = false;
51 static int def_NR_new_s_context = 259;
52 #undef __NR_new_s_context
53 static int __NR_new_s_context_rev0;
54 static int __NR_new_s_context_rev1;
56 static int new_s_context_rev0(int, int, int);
57 static int new_s_context_rev1(int, int *, int, int);
59 _syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags)
60 _syscall4(int, new_s_context_rev1, int, nbctx, int *, ctxs, int, remove_cap, int, flags)
63 new_s_context(int rev,
64 int nbctx, int *ctxs, int remove_cap, int flags)
74 case 0 : ctx = -1; break;
75 case 1 : ctx = ctxs[0]; break;
76 default : errno = EINVAL; return -1;
79 ret = new_s_context_rev0(ctx, remove_cap, flags);
85 ret = new_s_context_rev1(nbctx, ctxs, remove_cap, flags);
89 errno = EINVAL; return -1;
96 initVserverSyscalls(int s_context_NR)
98 int nr = (s_context_NR!=-1) ? s_context_NR : def_NR_new_s_context;
100 __NR_new_s_context_rev0 = __NR_new_s_context_rev1 = nr;
104 getAndClearEnv(char const *key, int dflt)
106 char *env = getenv(key);
109 if (env==0 || env[0]=='\0') res = dflt;
121 if (is_initialized) return;
123 initVserverSyscalls(getAndClearEnv("RPM_FAKE_S_CONTEXT_NR", -1));
124 INIT(RTLD_NEXT, execv);
125 //INIT(RTLD_NEXT, open);
127 is_initialized = true;
133 char *env = getenv("LD_PRELOAD");
136 // the const <-> non-const assignment is not an issue since the following modifying operations
137 // will not be executed in the const-case
138 env = env ? env : "";
139 pos = strstr(env, LIBNAME);
142 char *end_pos = pos + sizeof(LIBNAME);
143 bool is_end = (end_pos[-1]=='\0');
147 start_pos = strrchr(env, ':');
148 if (start_pos==0) start_pos = env;
149 else if (!is_end) ++start_pos;
151 if (is_end) *start_pos = '\0';
152 else memmove(start_pos, end_pos, strlen(end_pos)+1);
156 printf("env='%s'\n", env);
159 if (*env=='\0') unsetenv("LD_PRELOAD");
163 execvWorker(char const *path, char * const argv[])
168 printf("+execvWorker\n");
169 ctx = getAndClearEnv("RPM_FAKE_CTX", -1);
170 if ( (res=new_s_context(getAndClearEnv("RPM_FAKE_S_CONTEXT_REV", 0),
173 getAndClearEnv("RPM_FAKE_CAP", ~0x3404040f),
174 getAndClearEnv("RPM_FAKE_FLAGS", 0)))!=-1 &&
175 (res=execv_func(path, argv)!=-1) ) {}
176 printf("-execvWorker -> res=%u, err=%s\n",res,strerror(errno));
189 removeNamespaceMountsChild(void *params_v)
191 struct ExecvParams * params = params_v;
192 char buf[strlen(params->mnts)+1], *ptr;
194 strcpy(buf, params->mnts);
195 ptr = strtok(buf, ":");
197 system("cat /proc/mounts");
199 system("ls -l /proc/self/ /proc/self/fd/ /var/lib /var/lib/rpm/");
200 if (umount2(ptr, 0)==-1) { dprintf(2, "ptr='%s' -> ", ptr); perror("umount2()"); return -1; }
201 ptr = strtok(0, ":");
204 unsetenv("RPM_FAKE_NAMESPACE_MOUNTS");
205 return execvWorker(params->path, params->argv);
209 removeNamespaceMounts(char const *path, char * const argv[])
211 char const * mnts = getenv("RPM_FAKE_NAMESPACE_MOUNTS");
213 printf("mnts='%s'\n", mnts);
214 if (mnts==0) return execvWorker(path, argv);
217 printf("l=%u\n", __LINE__);
218 char buf[512 + 2*strlen(mnts)];
221 struct ExecvParams params = {
227 printf("l=%u\n", __LINE__);
230 system("mount -t proc none /proc");
231 system("cat /proc/mounts");
232 //system("pstree -h");
233 system("ls -l /proc/self/ /proc/self/fd/ /var/lib /var/lib/rpm/");
234 pid_t pid = clone(removeNamespaceMountsChild, buf+sizeof(buf)/2,
235 CLONE_NEWNS|SIGCHLD|CLONE_VFORK, ¶ms);
237 printf("l=%u\n", __LINE__);
238 if (pid==-1) return -1;
239 while ((p=waitpid(pid, &status, 0))==-1 &&
240 (errno==EINTR || errno==EAGAIN)) ;
241 if (p==-1) return -1;
243 printf("removeNamespaceMountsChild() -> status=%u\n", status);
245 if (WIFEXITED(status)) exit(WEXITSTATUS(status));
246 if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status));
253 execv(char const *path, char * const argv[]) __THROW
257 return removeNamespaceMounts(path, argv);