/[util-vserver]/util-vserver/src/rpm-fake.c
ViewVC logotype

Contents of /util-vserver/src/rpm-fake.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.31 - (show annotations) (download)
Sun Apr 10 12:27:25 2005 UTC (19 years ago) by ensc
Branch: MAIN
Changes since 1.30: +3 -1 lines
File MIME type: text/plain
send the signals for endgrent() and endpwent()

1 // $Id: rpm-fake.c,v 1.30 2005/03/23 02:08:45 ensc Exp $ --*- c++ -*--
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //
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.
8 //
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.
13 //
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.
17 //
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include "pathconfig.h"
24 #include "util.h"
25
26 #include <lib/vserver.h>
27 #include <lib/internal.h>
28 #include <lib_internal/sys_clone.h>
29
30 #include <sys/socket.h>
31 #include <dlfcn.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <asm/unistd.h>
37 #include <string.h>
38 #include <stdbool.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdarg.h>
42 #include <sys/mount.h>
43 #include <linux/fs.h>
44 #include <sched.h>
45 #include <signal.h>
46 #include <sys/types.h>
47 #include <sys/wait.h>
48 #include <sys/un.h>
49 #include <fcntl.h>
50 #include <pwd.h>
51 #include <grp.h>
52
53
54 // from selinux.h
55 // FIXME: add configure autodetection and include <selinux.h> directly
56 int rpm_execcon(unsigned int verified,
57 const char *filename,
58 char *const argv[], char *const envp[]);
59
60
61 #define ENSC_WRAPPERS_PREFIX "rpm-fake.so: "
62 #define ENSC_WRAPPERS_VSERVER 1
63 #define ENSC_WRAPPERS_UNISTD 1
64 #include <wrappers.h>
65
66 #undef _POSIX_SOURCE
67 #include "capability-compat.h"
68
69 #ifndef CLONE_NEWNS
70 # define CLONE_NEWNS 0x00020000
71 #endif
72
73 #define LIBNAME "rpm-fake.so"
74 #define PLATFORM_FILE "/etc/rpm/platform"
75
76 #define INIT(FILE,FUNC) FUNC##_func = ((__typeof__(FUNC) *) (xdlsym(FILE, #FUNC)))
77 #define DECLARE(FUNC) static __typeof__(FUNC) * FUNC##_func = 0
78
79 #define DEBUG 1
80
81 #define DBG_INIT 0x0001
82 #define DBG_VARIABLES 0x0002
83 #define DBG_RESOLVER 0x0004
84 #define DBG_EXECV 0x0008
85 #define DBG_ENV 0x0010
86 #define DBG_VERBOSE0 0x8000
87 #define DBG_VERBOSE1 (0x4000 | DBG_VERBOSE0)
88 #define DBG_VERBOSE2 (0x2000 | DBG_VERBOSE1)
89
90 int wrapper_exit_code = 255;
91
92 static xid_t ctx = VC_NOCTX;
93 static uint32_t caps = ~0;
94 static int flags = 0;
95 static char const * mnts = 0;
96 static char const * root = 0;
97 static int pw_sock = -1;
98 static int sync_sock = -1;
99 static unsigned int debug_level = 0;
100
101 static bool is_initialized = false;
102
103 //DECLARE(rpm_execcon);
104 //DECLARE(execv);
105 DECLARE(getpwnam);
106 DECLARE(getgrnam);
107 DECLARE(endpwent);
108 DECLARE(endgrent);
109
110 static void initRPMFake() __attribute__((__constructor__));
111 static void exitRPMFake() __attribute__((__destructor__));
112
113 static inline bool
114 isDbgLevel(unsigned int level)
115 {
116 return ((debug_level&level)==level);
117 }
118
119 static void *
120 xdlsym(void *handle, const char *symbol)
121 {
122 void *res = dlsym(handle, symbol);
123 if (res==0) {
124 char const *error = dlerror();
125 Vwrite(2, symbol, strlen(symbol));
126 Vwrite(2, ": ", 2);
127 Vwrite(2, error, strlen(error));
128 Vwrite(2, "\n", 2);
129
130 _exit(255);
131 }
132
133 return res;
134 }
135
136 static void
137 showHelp()
138 {
139 WRITE_MSG(1,
140 "Usage: LD_PRELOAD=" LIBNAME " <executable> <args>*\n\n"
141 LIBNAME " unterstands the following environment variables:\n"
142 " $RPM_FAKE_RESOLVER ... program which does the NSS resolving (defaults\n"
143 " to " RESOLVER_PROG ")\n"
144 " $RPM_FAKE_RESOLVER_UID ... uid of the resolver program\n"
145 " $RPM_FAKE_RESOLVER_GID ... gid of the resolver program\n"
146 " $RPM_FAKE_CTX ... vserver context which shall be used for resolver\n"
147 " and scriptlets\n"
148 " $RPM_FAKE_CAP ... linux capability remove-mask for the context\n"
149 " $RPM_FAKE_FLAGS ... vserver flags of the context\n"
150 " $RPM_FAKE_CHROOT ... directory of the chroot environment\n"
151 " $RPM_FAKE_NAMESPACE_MOUNTS\n"
152 " ... colon separated list of directories which will\n"
153 " umounted before scriptlet execution\n\n"
154 " $RPM_FAKE_HELP ... shows this message\n"
155 " $RPM_FAKE_VERSION ... shows the version of this program\n\n"
156 " $RPM_FAKE_DEBUG ... sets the debuglevel bitmask\n\n"
157 "Please report bugs to " PACKAGE_BUGREPORT "\n");
158 exit(0);
159 }
160
161 static void
162 showVersion()
163 {
164 WRITE_MSG(1,
165 LIBNAME " " VERSION " -- wrapper around rpm\n"
166 "This program is part of " PACKAGE_STRING "\n\n"
167 "Copyright (C) 2003 Enrico Scholz\n"
168 VERSION_COPYRIGHT_DISCLAIMER);
169 exit(0);
170 }
171
172 static void
173 unsetPreloadEnv()
174 {
175 char *env = getenv("LD_PRELOAD");
176 char *pos;
177
178 // the const <-> non-const assignment is not an issue since the following
179 // modifying operations will not be executed in the const-case
180 env = env ? env : "";
181 pos = strstr(env, LIBNAME);
182
183 if (pos!=0) {
184 char *end_pos = pos + sizeof(LIBNAME);
185 bool is_end = (end_pos[-1]=='\0');
186 char *start_pos;
187
188 end_pos[-1] = '\0';
189 start_pos = strrchr(env, ':');
190 if (start_pos==0) start_pos = env;
191 else if (!is_end) ++start_pos;
192
193 if (is_end) *start_pos = '\0';
194 else memmove(start_pos, end_pos, strlen(end_pos)+1);
195 }
196
197 #ifdef DEBUG
198 if (isDbgLevel(DBG_VERBOSE1|DBG_VARIABLES)) {
199 WRITE_MSG(2, "env='");
200 WRITE_STR(2, env);
201 WRITE_MSG(2, "'\n");
202 }
203 #endif
204
205 if (*env=='\0') unsetenv("LD_PRELOAD");
206 }
207
208 static void
209 clearEnv()
210 {
211 if (isDbgLevel(DBG_ENV)) WRITE_MSG(2, "clearEnv()\n");
212
213 unsetenv("RPM_FAKE_S_CONTEXT_REV");
214 unsetenv("RPM_FAKE_S_CONTEXT_NR");
215 unsetenv("RPM_FAKE_CTX");
216 unsetenv("RPM_FAKE_FLAGS");
217 unsetenv("RPM_FAKE_CHROOT");
218 unsetenv("RPM_FAKE_NAMESPACE_MOUNTS");
219
220 unsetenv("RPM_FAKE_RESOLVER_GID");
221 unsetenv("RPM_FAKE_RESOLVER_UID");
222 unsetenv("RPM_FAKE_RESOLVER");
223 unsetenv("RPM_FAKE_PWSOCKET");
224
225 unsetenv("RPM_FAKE_DEBUG");
226
227 unsetPreloadEnv();
228 }
229
230 static int
231 getDefaultEnv(char const *key, int dflt)
232 {
233 char *env = getenv(key);
234 int res;
235
236 if (env==0 || env[0]=='\0') res = dflt;
237 else res = atoi(env);
238
239 return res;
240 }
241
242 /// \returns true iff we are in ctx after leaving this function
243 static bool
244 setupContext(xid_t xid, char const **xid_str)
245 {
246 bool res = false;
247
248 if (vc_isSupported(vcFEATURE_MIGRATE)) {
249 xid_t rc=VC_NOCTX;
250
251 if ((xid==VC_DYNAMIC_XID || !vc_is_dynamic_xid(xid)) &&
252 (rc=vc_ctx_create(xid))==VC_NOCTX &&
253 errno!=EEXIST) {
254 perror(ENSC_WRAPPERS_PREFIX "vc_create_context()");
255 exit(255);
256 }
257
258 if (rc!=VC_NOCTX) {
259 char buf[sizeof(xid_t)*3 + 128];
260 size_t l;
261 struct vc_ctx_caps caps;
262
263 strcpy(buf, "rpm-fake.so #");
264 l = utilvserver_fmt_uint(buf+sizeof("rpm-fake.so #")-1, getppid());
265 Evc_set_vhi_name(rc, vcVHI_CONTEXT, buf, sizeof("rpm-fake.so #")+l-1);
266
267 caps.ccaps = 0ull;
268 caps.cmask = ~0ull;
269 caps.bcaps = ~vc_get_insecurebcaps();
270 caps.bmask = ~0ull;
271 Evc_set_ccaps(rc, &caps);
272
273 // context will be activated later...
274
275 xid = rc;
276 res = true;
277 }
278 }
279
280 if (xid==VC_DYNAMIC_XID)
281 *xid_str = 0;
282 else {
283 char buf[sizeof(xid_t)*3 + 2];
284 size_t l;
285
286 l = utilvserver_fmt_uint(buf, xid); buf[l] = '\0';
287 *xid_str = strdup(buf);
288 }
289
290 Ewrite(3, &xid, sizeof xid);
291 return res;
292 }
293
294 #if 0
295 static void
296 initPwSocket()
297 {
298 char const * sock_name = getenv("RPM_FAKE_PWSOCKET");
299 if (sock_name!=0) {
300 int flag;
301 struct sockaddr_un addr = {
302 .sun_family = AF_UNIX,
303 };
304
305 strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path)-1);
306 addr.sun_path[sizeof(addr.sun_path)-1]='\0';
307
308 if ((pw_sock=socket(AF_UNIX, SOCK_STREAM, 0))==-1 ||
309 connect(pw_sock, (struct sockaddr *)(&addr), sizeof addr)==-1 ||
310 (flag=fcntl(pw_sock, F_GETFD))==-1 ||
311 fcntl(pw_sock, F_SETFD, flag | FD_CLOEXEC)==-1) {
312 perror(ENSC_WRAPPERS_PREFIX "error while initializing pw-socket");
313 exit(255);
314 }
315 }
316 }
317 #else
318 static void
319 initPwSocket()
320 {
321 char const * resolver = getenv("RPM_FAKE_RESOLVER");
322 if (resolver==0) resolver=RESOLVER_PROG;
323
324 if (resolver!=0 && *resolver!='\0') {
325 int res_sock[2];
326 int sync_pipe[2];
327 pid_t pid;
328 char const * uid=0;
329 char const * gid=0;
330
331 uid=getenv("RPM_FAKE_RESOLVER_UID");
332 gid=getenv("RPM_FAKE_RESOLVER_GID");
333
334 if (socketpair(AF_UNIX, SOCK_STREAM, 0, res_sock)==-1 ||
335 pipe(sync_pipe)==-1 ||
336 fcntl(res_sock[0], F_SETFD, FD_CLOEXEC)==-1 ||
337 fcntl(sync_pipe[0], F_SETFD, FD_CLOEXEC)==-1) {
338 perror(ENSC_WRAPPERS_PREFIX "failed to create/initialize resolver-socket or pipe");
339 exit(255);
340 }
341
342 pid = fork();
343 if (pid==-1) {
344 perror(ENSC_WRAPPERS_PREFIX "fork()");
345 exit(255);
346 }
347
348 if (pid==0) {
349 char const *args[20];
350 char const **ptr = args;
351 char const *env[] = { "HOME=/", "PATH=/bin:/usr/bin", 0 };
352 char const *xid_str;
353 char flag_str[ sizeof(flags)*3 + 2];
354 char caps_str[ sizeof(caps)*3 + 2];
355
356 clearEnv();
357
358 setsid();
359 dup2(res_sock[1], 0);
360 dup2(res_sock[1], 1);
361 if (sync_pipe[1]!=3) {
362 close(3);
363 dup2(sync_pipe[1], 3);
364 close(sync_pipe[1]);
365 }
366 close(res_sock[1]);
367 /* ... *socket[0] are marked as close-on-exec ...*/
368
369 flag_str[utilvserver_fmt_uint(flag_str, flags)] = '\0';
370 caps_str[utilvserver_fmt_uint(caps_str, caps)] = '\0';
371
372 *ptr++ = resolver;
373 *ptr++ = "-F"; *ptr++ = flag_str;
374 *ptr++ = "-C"; *ptr++ = caps_str;
375 if (root) { *ptr++ = "-r"; *ptr++ = "."; }
376 if (uid) { *ptr++ = "-u"; *ptr++ = uid; }
377 if (gid) { *ptr++ = "-g"; *ptr++ = gid; }
378
379 if (root) Echdir(root);
380
381 if (setupContext(ctx, &xid_str)) { *ptr++ = "-s"; }
382 else if (xid_str) { *ptr++ = "-c"; *ptr++ = xid_str; }
383
384 *ptr++ = 0;
385 execve(resolver, (char **)args, (char **)env);
386 perror(ENSC_WRAPPERS_PREFIX "failed to exec resolver");
387 exit(255);
388 }
389 else {
390 uint8_t c;
391
392 close(res_sock[1]);
393 close(sync_pipe[1]);
394 pw_sock = res_sock[0];
395 sync_sock = sync_pipe[0];
396
397 if (read(sync_sock, &ctx, sizeof ctx)!=sizeof(ctx) ||
398 read(sync_sock, &c, 1)!=1 ||
399 write(pw_sock, ".", 1)!=1 ||
400 read(pw_sock, &c, 1)!=1 ||
401 c!='.') {
402 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "failed to initialize communication with resolver\n");
403 exit(255);
404 }
405
406 if (wait4(pid, 0, WNOHANG,0)==-1) {
407 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX" unexpected initialization-error of resolver\n");
408 exit(255);
409 }
410 }
411 }
412 }
413 #endif
414
415 static void
416 reduceCapabilities()
417 {
418 struct __user_cap_header_struct header;
419 struct __user_cap_data_struct user;
420
421 header.version = _LINUX_CAPABILITY_VERSION;
422 header.pid = 0;
423
424 if (capget(&header, &user)==-1) {
425 perror("capget()");
426 exit(wrapper_exit_code);
427 }
428
429 user.effective &= ~(1<<CAP_MKNOD);
430 user.permitted &= ~(1<<CAP_MKNOD);
431 user.inheritable &= ~(1<<CAP_MKNOD);
432
433 if (capset(&header, &user)==-1) {
434 perror("capset()");
435 exit(wrapper_exit_code);
436 }
437 }
438
439 static void
440 initEnvironment()
441 {
442 int syscall_rev;
443 int syscall_nr;
444
445 if (is_initialized) return;
446
447 syscall_rev = getDefaultEnv("RPM_FAKE_S_CONTEXT_REV", 0);
448 syscall_nr = getDefaultEnv("RPM_FAKE_S_CONTEXT_NR", 273);
449
450 #ifdef VC_ENABLE_API_LEGACY
451 {
452 extern void vc_init_internal_legacy(int ctx_rev, int ctx_number,
453 int ipv4_rev, int ipv4_number);
454
455 vc_init_internal_legacy(syscall_rev, syscall_nr, 3, 274);
456 }
457 #endif
458
459 ctx = getDefaultEnv("RPM_FAKE_CTX", VC_DYNAMIC_XID);
460 caps = getDefaultEnv("RPM_FAKE_CAP", ~0x3404040f);
461 flags = getDefaultEnv("RPM_FAKE_FLAGS", 0);
462 root = getenv("RPM_FAKE_CHROOT");
463 mnts = getenv("RPM_FAKE_NAMESPACE_MOUNTS");
464 if (mnts && *mnts) mnts = strdup(mnts);
465 else mnts = 0;
466
467 #if DEBUG
468 if (isDbgLevel(DBG_VERBOSE1))
469 dprintf(2, "ctx=%u, caps=%016x, flags=%016x,\nroot='%s',\nmnts='%s'\n",
470 ctx, caps, flags, root, mnts);
471 #endif
472
473 is_initialized = true;
474 }
475
476 static void
477 initSymbols()
478 {
479 //INIT(RTLD_NEXT, rpm_execcon);
480 //INIT(RTLD_NEXT, execv);
481 INIT(RTLD_NEXT, getgrnam);
482 INIT(RTLD_NEXT, getpwnam);
483 INIT(RTLD_NEXT, endpwent);
484 INIT(RTLD_NEXT, endgrent);
485 }
486
487 void
488 initRPMFake()
489 {
490 if (getenv("RPM_FAKE_VERSION")) showVersion();
491 if (getenv("RPM_FAKE_HELP")) showHelp();
492
493 debug_level = getDefaultEnv("RPM_FAKE_DEBUG", 0);
494
495 if (isDbgLevel(DBG_INIT)) WRITE_MSG(2, ">>>>> initRPMFake <<<<<\n");
496
497 reduceCapabilities();
498 initSymbols();
499 initEnvironment();
500 initPwSocket();
501
502 #if 0
503 if (isDbgLevel(DBG_VARIABLES|DBG_VERBOSE2)) {
504
505 }
506 #endif
507 }
508
509 void
510 exitRPMFake()
511 {
512 if (isDbgLevel(DBG_INIT)) WRITE_MSG(2, ">>>>> exitRPMFake <<<<<\n");
513 if (pw_sock!=-1) {
514 uint8_t c;
515 if (read(sync_sock, &c, 1)!=1) { /*...*/ }
516 if (write(pw_sock, "Q", 1)!=1) { /*...*/ }
517 }
518 }
519
520
521 //============ the worker part ===========
522
523
524 static bool
525 doPwStringRequest(uint32_t *result, char style, char const *name)
526 {
527 size_t len = strlen(name);
528 uint8_t code;
529 uint8_t c;
530
531 return (TEMP_FAILURE_RETRY(read (sync_sock, &c, 1))==1 &&
532
533 TEMP_FAILURE_RETRY(write(pw_sock, &style, 1))==1 &&
534 TEMP_FAILURE_RETRY(write(pw_sock, &len, sizeof len))==sizeof(len) &&
535 TEMP_FAILURE_RETRY(write(pw_sock, name, len))==(ssize_t)(len) &&
536 TEMP_FAILURE_RETRY(read (pw_sock, &code, sizeof code))==sizeof(code) &&
537 TEMP_FAILURE_RETRY(read (pw_sock, result, sizeof *result))==sizeof(*result) &&
538 code!=0);
539 }
540
541 struct passwd *
542 getpwnam(const char * name)
543 {
544 if (pw_sock==-1) return getpwnam_func(name);
545 else {
546 static struct passwd res = {
547 .pw_passwd = "*",
548 .pw_gid = -1,
549 .pw_gecos = "",
550 .pw_dir = "/",
551 .pw_shell = "/bin/false"
552 };
553
554 res.pw_name = (char *)(name);
555 if (!doPwStringRequest(&res.pw_uid, 'P', name)) return 0;
556
557 return &res;
558 }
559 }
560
561 struct group *
562 getgrnam(const char * name)
563 {
564 if (pw_sock==-1) return getgrnam_func(name);
565 else {
566 static struct group res = {
567 .gr_passwd = "*",
568 .gr_mem = 0
569 };
570
571 res.gr_name = (char *)(name);
572 if (!doPwStringRequest(&res.gr_gid, 'G', name)) return 0;
573
574 return &res;
575 }
576 }
577
578 void
579 endgrent()
580 {
581 if (pw_sock==-1) endgrent_func();
582 TEMP_FAILURE_RETRY(write(pw_sock, "Cg", 2));
583 }
584
585 void
586 endpwent()
587 {
588 if (pw_sock==-1) endpwent_func();
589 TEMP_FAILURE_RETRY(write(pw_sock, "Cp", 2));
590 }
591
592
593 static int
594 execvWorker(char const *path, char * const argv[], char * const envp[])
595 {
596 int res = -1;
597
598 if (vc_isSupported(vcFEATURE_MIGRATE))
599 res = vc_ctx_migrate(ctx);
600 else {
601 #ifdef VC_ENABLE_API_COMPAT
602 res = vc_new_s_context(ctx,caps,flags);
603 #else
604 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not change context: migrate kernel feature missing and 'compat' API disabled\n");
605 #endif
606 }
607
608 clearEnv();
609
610 if (res!=-1)
611 res=execve(path, argv, envp);
612
613 return res;
614 }
615
616 struct ExecvParams
617 {
618 char const * path;
619 char * const * argv;
620 char * const * envp;
621 char const * mnts;
622 };
623
624 static int
625 removeNamespaceMountsChild(struct ExecvParams const *params)
626 {
627 char buf[strlen(params->mnts)+1], *ptr;
628
629 strcpy(buf, params->mnts);
630 ptr = strtok(buf, ":");
631 while (ptr) {
632 if (umount2(ptr, 0)==-1) {
633 // FIXME: What is the semantic for CLONE_NEWNS? Is it ok that mounts in
634 // chroots are visible only, when chroot is on /dev/root?
635 //
636 // For now, ignore any errors, but future versions should handle them.
637
638 //return -1;
639 }
640 ptr = strtok(0, ":");
641 }
642
643 return execvWorker(params->path, params->argv, params->envp);
644 }
645
646 static int
647 removeNamespaceMounts(char const *path,
648 char * const argv[], char * const envp[])
649 {
650 if (mnts==0) return execvWorker(path, argv, envp);
651
652 {
653 int status;
654 pid_t p, pid;
655 struct ExecvParams params;
656
657 params.path = path;
658 params.argv = argv;
659 params.envp = envp;
660 params.mnts = mnts;
661
662 // the rpmlib signal-handler is still active; use the default one to
663 // make wait4() working...
664 signal(SIGCHLD, SIG_DFL);
665
666 #ifdef NDEBUG
667 pid = sys_clone(CLONE_NEWNS|SIGCHLD|CLONE_VFORK, 0);
668 #else
669 pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0);
670 #endif
671
672 switch (pid) {
673 case -1 : return -1;
674 case 0 : _exit(removeNamespaceMountsChild(&params));
675 default : break;
676 }
677
678 while ((p=wait4(pid, &status, 0,0))==-1 &&
679 (errno==EINTR || errno==EAGAIN)) ;
680
681 if (p==-1) return -1;
682
683 if (WIFEXITED(status)) _exit(WEXITSTATUS(status));
684 if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status));
685
686 return -1;
687 }
688 }
689
690
691 int
692 execv(char const *path, char * const argv[])
693 {
694 extern char **environ;
695
696 if (isDbgLevel(DBG_EXECV)) {
697 WRITE_MSG(2, "execv('");
698 WRITE_STR(2, path);
699 WRITE_MSG(2, "', ...)\n");
700 }
701
702 return removeNamespaceMounts(path, argv, environ);
703 }
704
705 int
706 rpm_execcon(unsigned int UNUSED verified,
707 const char *filename,
708 char *const argv[], char *const envp[])
709 {
710 if (isDbgLevel(DBG_EXECV)) {
711 WRITE_MSG(2, "rpm_execcon(..., '");
712 WRITE_STR(2, filename);
713 WRITE_MSG(2, "', ...)\n");
714 }
715
716 return removeNamespaceMounts(filename, argv, envp);
717 }
718
719 int
720 is_selinux_enabled()
721 {
722 return 0;
723 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26