1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2022 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
23 #include <linux/capability.h>
24 #include <linux/sched.h>
26 #include <linux/wait.h>
31 #include <sys/capability.h>
32 #include <sys/epoll.h>
33 #include <sys/eventfd.h>
34 #include <sys/mount.h>
35 #include <sys/personality.h>
36 #include <sys/prctl.h>
37 #include <sys/resource.h>
38 #include <sys/signalfd.h>
39 #include <sys/timerfd.h>
40 #include <sys/types.h>
45 #include <netlink/route/link.h>
53 #include <pakfire/arch.h>
54 #include <pakfire/cgroup.h>
55 #include <pakfire/jail.h>
56 #include <pakfire/logging.h>
57 #include <pakfire/mount.h>
58 #include <pakfire/pakfire.h>
59 #include <pakfire/private.h>
60 #include <pakfire/pwd.h>
61 #include <pakfire/string.h>
62 #include <pakfire/util.h>
64 #define BUFFER_SIZE 1024 * 64
65 #define ENVIRON_SIZE 128
66 #define EPOLL_MAX_EVENTS 2
67 #define MAX_MOUNTPOINTS 8
69 // The default environment that will be set for every command
70 static const struct environ
{
75 { "LANG", "C.utf-8" },
76 { "PATH", "/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin", },
79 // Tell everything that it is running inside a Pakfire container
80 { "container", "pakfire" },
84 struct pakfire_jail_mountpoint
{
85 char source
[PATH_MAX
];
86 char target
[PATH_MAX
];
91 struct pakfire
* pakfire
;
94 // A unique ID for each jail
96 char __uuid
[UUID_STR_LEN
];
102 struct itimerspec timeout
;
105 struct pakfire_cgroup
* cgroup
;
108 char* env
[ENVIRON_SIZE
];
111 struct pakfire_jail_mountpoint mountpoints
[MAX_MOUNTPOINTS
];
112 unsigned int num_mountpoints
;
115 struct pakfire_jail_callbacks
{
117 pakfire_jail_log_callback log
;
122 struct pakfire_log_buffer
{
123 char data
[BUFFER_SIZE
];
127 struct pakfire_jail_exec
{
130 // PID (of the child)
134 // Process status (from waitid)
137 // FD to notify the client that the parent has finished initialization
141 struct pakfire_jail_pipes
{
153 struct pakfire_jail_communicate
{
154 pakfire_jail_communicate_in in
;
155 pakfire_jail_communicate_out out
;
160 struct pakfire_jail_buffers
{
161 struct pakfire_log_buffer stdout
;
162 struct pakfire_log_buffer stderr
;
165 struct pakfire_log_buffer log_INFO
;
166 struct pakfire_log_buffer log_ERROR
;
167 struct pakfire_log_buffer log_DEBUG
;
170 struct pakfire_cgroup
* cgroup
;
171 struct pakfire_cgroup_stats cgroup_stats
;
174 static int clone3(struct clone_args
* args
, size_t size
) {
175 return syscall(__NR_clone3
, args
, size
);
178 static int pidfd_send_signal(int pidfd
, int sig
, siginfo_t
* info
, unsigned int flags
) {
179 return syscall(SYS_pidfd_send_signal
, pidfd
, sig
, info
, flags
);
182 static int pivot_root(const char* new_root
, const char* old_root
) {
183 return syscall(SYS_pivot_root
, new_root
, old_root
);
186 static int pakfire_jail_exec_has_flag(
187 const struct pakfire_jail_exec
* ctx
, const enum pakfire_jail_exec_flags flag
) {
188 return ctx
->flags
& flag
;
191 static void pakfire_jail_free(struct pakfire_jail
* jail
) {
192 DEBUG(jail
->pakfire
, "Freeing jail at %p\n", jail
);
195 for (unsigned int i
= 0; jail
->env
[i
]; i
++)
199 pakfire_cgroup_unref(jail
->cgroup
);
201 pakfire_unref(jail
->pakfire
);
206 Passes any log messages on to the default pakfire log callback
208 static int pakfire_jail_default_log_callback(struct pakfire
* pakfire
, void* data
,
209 int priority
, const char* line
, size_t length
) {
212 INFO(pakfire
, "%s", line
);
216 ERROR(pakfire
, "%s", line
);
221 DEBUG(pakfire
, "%s", line
);
229 static const char* pakfire_jail_uuid(struct pakfire_jail
* jail
) {
231 uuid_unparse_lower(jail
->uuid
, jail
->__uuid
);
236 static int pakfire_jail_setup_interactive_env(struct pakfire_jail
* jail
) {
238 int r
= pakfire_jail_set_env(jail
, "PS1", "pakfire-jail \\w> ");
243 char* TERM
= secure_getenv("TERM");
245 r
= pakfire_jail_set_env(jail
, "TERM", TERM
);
251 char* LANG
= secure_getenv("LANG");
253 r
= pakfire_jail_set_env(jail
, "LANG", LANG
);
261 PAKFIRE_EXPORT
int pakfire_jail_create(struct pakfire_jail
** jail
, struct pakfire
* pakfire
) {
264 const char* arch
= pakfire_get_effective_arch(pakfire
);
266 // Allocate a new jail
267 struct pakfire_jail
* j
= calloc(1, sizeof(*j
));
272 j
->pakfire
= pakfire_ref(pakfire
);
274 // Initialize reference counter
277 // Generate a random UUID
278 uuid_generate_random(j
->uuid
);
280 DEBUG(j
->pakfire
, "Allocated new jail at %p\n", j
);
282 // Set the default logging callback
283 pakfire_jail_set_log_callback(j
, pakfire_jail_default_log_callback
, NULL
);
285 // Set default environment
286 for (const struct environ
* e
= ENV
; e
->key
; e
++) {
287 r
= pakfire_jail_set_env(j
, e
->key
, e
->val
);
292 // Enable all CPU features that CPU has to offer
293 if (!pakfire_arch_is_supported_by_host(arch
)) {
294 r
= pakfire_jail_set_env(j
, "QEMU_CPU", "max");
299 // Set container UUID
300 r
= pakfire_jail_set_env(j
, "container_uuid", pakfire_jail_uuid(j
));
304 // Disable systemctl to talk to systemd
305 if (!pakfire_on_root(j
->pakfire
)) {
306 r
= pakfire_jail_set_env(j
, "SYSTEMD_OFFLINE", "1");
316 pakfire_jail_free(j
);
321 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_ref(struct pakfire_jail
* jail
) {
327 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_unref(struct pakfire_jail
* jail
) {
328 if (--jail
->nrefs
> 0)
331 pakfire_jail_free(jail
);
337 PAKFIRE_EXPORT
void pakfire_jail_set_log_callback(struct pakfire_jail
* jail
,
338 pakfire_jail_log_callback callback
, void* data
) {
339 jail
->callbacks
.log
= callback
;
340 jail
->callbacks
.log_data
= data
;
345 PAKFIRE_EXPORT
int pakfire_jail_nice(struct pakfire_jail
* jail
, int nice
) {
346 // Check if nice level is in range
347 if (nice
< -19 || nice
> 20) {
358 int pakfire_jail_set_cgroup(struct pakfire_jail
* jail
, struct pakfire_cgroup
* cgroup
) {
359 // Free any previous cgroup
361 pakfire_cgroup_unref(jail
->cgroup
);
365 // Set any new cgroup
367 DEBUG(jail
->pakfire
, "Setting cgroup %p\n", cgroup
);
369 jail
->cgroup
= pakfire_cgroup_ref(cgroup
);
378 // Returns the length of the environment
379 static unsigned int pakfire_jail_env_length(struct pakfire_jail
* jail
) {
382 // Count everything in the environment
383 for (char** e
= jail
->env
; *e
; e
++)
389 // Finds an existing environment variable and returns its index or -1 if not found
390 static int pakfire_jail_find_env(struct pakfire_jail
* jail
, const char* key
) {
396 const size_t length
= strlen(key
);
398 for (unsigned int i
= 0; jail
->env
[i
]; i
++) {
399 if ((pakfire_string_startswith(jail
->env
[i
], key
)
400 && *(jail
->env
[i
] + length
) == '=')) {
409 // Returns the value of an environment variable or NULL
410 PAKFIRE_EXPORT
const char* pakfire_jail_get_env(struct pakfire_jail
* jail
,
412 int i
= pakfire_jail_find_env(jail
, key
);
416 return jail
->env
[i
] + strlen(key
) + 1;
419 // Sets an environment variable
420 PAKFIRE_EXPORT
int pakfire_jail_set_env(struct pakfire_jail
* jail
,
421 const char* key
, const char* value
) {
422 // Find the index where to write this value to
423 int i
= pakfire_jail_find_env(jail
, key
);
425 i
= pakfire_jail_env_length(jail
);
427 // Return -ENOSPC when the environment is full
428 if (i
>= ENVIRON_SIZE
) {
433 // Free any previous value
437 // Format and set environment variable
438 asprintf(&jail
->env
[i
], "%s=%s", key
, value
);
440 DEBUG(jail
->pakfire
, "Set environment variable: %s\n", jail
->env
[i
]);
445 // Imports an environment
446 PAKFIRE_EXPORT
int pakfire_jail_import_env(struct pakfire_jail
* jail
, const char* env
[]) {
454 // Copy environment variables
455 for (unsigned int i
= 0; env
[i
]; i
++) {
456 r
= pakfire_string_partition(env
[i
], "=", &key
, &val
);
461 r
= pakfire_jail_set_env(jail
, key
, val
);
478 PAKFIRE_EXPORT
int pakfire_jail_set_timeout(
479 struct pakfire_jail
* jail
, unsigned int timeout
) {
481 jail
->timeout
.it_value
.tv_sec
= timeout
;
484 DEBUG(jail
->pakfire
, "Timeout set to %d second(s)\n", timeout
);
486 DEBUG(jail
->pakfire
, "Timeout disabled\n");
491 static int pakfire_jail_create_timer(struct pakfire_jail
* jail
) {
494 // Nothing to do if no timeout has been set
495 if (!jail
->timeout
.it_value
.tv_sec
)
498 // Create a new timer
499 const int fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
501 ERROR(jail
->pakfire
, "Could not create timer: %m\n");
506 r
= timerfd_settime(fd
, 0, &jail
->timeout
, NULL
);
508 ERROR(jail
->pakfire
, "Could not arm timer: %m\n");
523 static int pakfire_jail_handle_signals(struct pakfire_jail
* jail
) {
528 sigaddset(&mask
, SIGINT
);
531 r
= sigprocmask(SIG_BLOCK
, &mask
, NULL
);
533 ERROR(jail
->pakfire
, "Failed to block signals: %m\n");
537 // Create a file descriptor
538 r
= signalfd(-1, &mask
, SFD_NONBLOCK
|SFD_CLOEXEC
);
540 ERROR(jail
->pakfire
, "Failed to create signalfd: %m\n");
548 This function replaces any logging in the child process.
550 All log messages will be sent to the parent process through their respective pipes.
552 static void pakfire_jail_log(void* data
, int priority
, const char* file
,
553 int line
, const char* fn
, const char* format
, va_list args
) {
554 struct pakfire_jail_pipes
* pipes
= (struct pakfire_jail_pipes
*)data
;
559 fd
= pipes
->log_INFO
[1];
563 fd
= pipes
->log_ERROR
[1];
568 fd
= pipes
->log_DEBUG
[1];
570 #endif /* ENABLE_DEBUG */
572 // Ignore any messages of an unknown priority
577 // Send the log message
579 vdprintf(fd
, format
, args
);
582 static int pakfire_jail_log_buffer_is_full(const struct pakfire_log_buffer
* buffer
) {
583 return (sizeof(buffer
->data
) == buffer
->used
);
587 This function reads as much data as it can from the file descriptor.
588 If it finds a whole line in it, it will send it to the logger and repeat the process.
589 If not newline character is found, it will try to read more data until it finds one.
591 static int pakfire_jail_handle_log(struct pakfire_jail
* jail
,
592 struct pakfire_jail_exec
* ctx
, int priority
, int fd
,
593 struct pakfire_log_buffer
* buffer
, pakfire_jail_communicate_out callback
, void* data
) {
594 char line
[BUFFER_SIZE
+ 1];
596 // Fill up buffer from fd
597 if (buffer
->used
< sizeof(buffer
->data
)) {
598 ssize_t bytes_read
= read(fd
, buffer
->data
+ buffer
->used
,
599 sizeof(buffer
->data
) - buffer
->used
);
602 if (bytes_read
< 0) {
603 ERROR(jail
->pakfire
, "Could not read from fd %d: %m\n", fd
);
607 // Update buffer size
608 buffer
->used
+= bytes_read
;
611 // See if we have any lines that we can write
612 while (buffer
->used
) {
613 // Search for the end of the first line
614 char* eol
= memchr(buffer
->data
, '\n', buffer
->used
);
618 // If the buffer is full, we send the content to the logger and try again
619 // This should not happen in practise
620 if (pakfire_jail_log_buffer_is_full(buffer
)) {
621 DEBUG(jail
->pakfire
, "Logging buffer is full. Sending all content\n");
623 eol
= buffer
->data
+ sizeof(buffer
->data
) - 1;
625 // Otherwise we might have only read parts of the output
630 // Find the length of the string
631 size_t length
= eol
- buffer
->data
+ 1;
633 // Copy the line into the buffer
634 memcpy(line
, buffer
->data
, length
);
636 // Terminate the string
641 int r
= callback(jail
->pakfire
, data
, priority
, line
, length
);
643 ERROR(jail
->pakfire
, "The logging callback returned an error: %d\n", r
);
648 // Remove line from buffer
649 memmove(buffer
->data
, buffer
->data
+ length
, buffer
->used
- length
);
650 buffer
->used
-= length
;
656 static int pakfire_jail_stream_stdin(struct pakfire_jail
* jail
,
657 struct pakfire_jail_exec
* ctx
, const int fd
) {
660 // Nothing to do if there is no stdin callback set
661 if (!ctx
->communicate
.in
) {
662 DEBUG(jail
->pakfire
, "Callback for standard input is not set\n");
666 // Skip if the writing pipe has already been closed
667 if (!ctx
->pipes
.stdin
[1])
670 DEBUG(jail
->pakfire
, "Streaming standard input...\n");
672 // Calling the callback
673 r
= ctx
->communicate
.in(jail
->pakfire
, ctx
->communicate
.data
, fd
);
675 DEBUG(jail
->pakfire
, "Standard input callback finished: %d\n", r
);
677 // The callback signaled that it has written everything
679 DEBUG(jail
->pakfire
, "Closing standard input pipe\n");
681 // Close the file-descriptor
684 // Reset the file-descriptor so it won't be closed again later
685 ctx
->pipes
.stdin
[1] = 0;
694 static int pakfire_jail_setup_pipe(struct pakfire_jail
* jail
, int (*fds
)[2], const int flags
) {
695 int r
= pipe2(*fds
, flags
);
697 ERROR(jail
->pakfire
, "Could not setup pipe: %m\n");
704 static void pakfire_jail_close_pipe(struct pakfire_jail
* jail
, int fds
[2]) {
705 for (unsigned int i
= 0; i
< 2; i
++)
711 This is a convenience function to fetch the reading end of a pipe and
712 closes the write end.
714 static int pakfire_jail_get_pipe_to_read(struct pakfire_jail
* jail
, int (*fds
)[2]) {
715 // Give the variables easier names to avoid confusion
716 int* fd_read
= &(*fds
)[0];
717 int* fd_write
= &(*fds
)[1];
719 // Close the write end of the pipe
725 // Return the read end
729 static int pakfire_jail_get_pipe_to_write(struct pakfire_jail
* jail
, int (*fds
)[2]) {
730 // Give the variables easier names to avoid confusion
731 int* fd_read
= &(*fds
)[0];
732 int* fd_write
= &(*fds
)[1];
734 // Close the read end of the pipe
740 // Return the write end
744 static int pakfire_jail_wait(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
746 struct epoll_event ev
;
747 struct epoll_event events
[EPOLL_MAX_EVENTS
];
748 struct signalfd_siginfo siginfo
;
752 // Fetch file descriptors from context
753 const int stdin
= pakfire_jail_get_pipe_to_write(jail
, &ctx
->pipes
.stdin
);
754 const int stdout
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stdout
);
755 const int stderr
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stderr
);
756 const int pidfd
= ctx
->pidfd
;
759 const int timerfd
= pakfire_jail_create_timer(jail
);
762 const int log_INFO
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_INFO
);
763 const int log_ERROR
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_ERROR
);
764 const int log_DEBUG
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_DEBUG
);
767 const int signalfd
= pakfire_jail_handle_signals(jail
);
769 // Make a list of all file descriptors we are interested in
771 stdin
, stdout
, stderr
, pidfd
, timerfd
, signalfd
, log_INFO
, log_ERROR
, log_DEBUG
,
775 epollfd
= epoll_create1(0);
777 ERROR(jail
->pakfire
, "Could not initialize epoll(): %m\n");
782 // Turn file descriptors into non-blocking mode and add them to epoll()
783 for (unsigned int i
= 0; i
< sizeof(fds
) / sizeof(*fds
); i
++) {
786 // Skip fds which were not initialized
790 ev
.events
= EPOLLHUP
;
793 ev
.events
|= EPOLLOUT
;
795 ev
.events
|= EPOLLIN
;
798 int flags
= fcntl(fd
, F_GETFL
, 0);
800 // Set modified flags
801 if (fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
) < 0) {
803 "Could not set file descriptor %d into non-blocking mode: %m\n", fd
);
810 if (epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fd
, &ev
) < 0) {
811 ERROR(jail
->pakfire
, "Could not add file descriptor %d to epoll(): %m\n", fd
);
819 // Loop for as long as the process is alive
821 int num
= epoll_wait(epollfd
, events
, EPOLL_MAX_EVENTS
, -1);
823 // Ignore if epoll_wait() has been interrupted
827 ERROR(jail
->pakfire
, "epoll_wait() failed: %m\n");
833 for (int i
= 0; i
< num
; i
++) {
834 int e
= events
[i
].events
;
835 int fd
= events
[i
].data
.fd
;
837 struct pakfire_log_buffer
* buffer
= NULL
;
838 pakfire_jail_communicate_out callback
= NULL
;
842 // Check if there is any data to be read
844 // Handle any changes to the PIDFD
846 // Call waidid() and store the result
847 r
= waitid(P_PIDFD
, ctx
->pidfd
, &ctx
->status
, WEXITED
);
849 ERROR(jail
->pakfire
, "waitid() failed: %m\n");
853 // Mark that we have ended so that we will process the remaining
854 // events from epoll() now, but won't restart the outer loop.
858 // Handle timer events
859 } else if (fd
== timerfd
) {
860 DEBUG(jail
->pakfire
, "Timer event received\n");
863 r
= read(timerfd
, garbage
, sizeof(garbage
));
865 ERROR(jail
->pakfire
, "Could not disarm timer: %m\n");
870 // Terminate the process if it hasn't already ended
872 DEBUG(jail
->pakfire
, "Terminating process...\n");
874 // Send SIGTERM to the process
875 r
= pidfd_send_signal(pidfd
, SIGKILL
, NULL
, 0);
877 ERROR(jail
->pakfire
, "Could not kill process: %m\n");
882 // There is nothing else to do
886 } else if (fd
== signalfd
) {
888 r
= read(signalfd
, &siginfo
, sizeof(siginfo
));
890 ERROR(jail
->pakfire
, "Could not read signal: %m\n");
894 DEBUG(jail
->pakfire
, "Received signal %d\n", siginfo
.ssi_signo
);
897 switch (siginfo
.ssi_signo
) {
898 // Pass SIGINT down to the child process
900 r
= pidfd_send_signal(pidfd
, siginfo
.ssi_signo
, NULL
, 0);
902 ERROR(jail
->pakfire
, "Could not send signal to process: %m\n");
908 ERROR(jail
->pakfire
, "Received unhandled signal %d\n",
913 // Don't fall through to log processing
916 // Handle logging messages
917 } else if (fd
== log_INFO
) {
918 buffer
= &ctx
->buffers
.log_INFO
;
921 callback
= jail
->callbacks
.log
;
922 data
= jail
->callbacks
.log_data
;
924 } else if (fd
== log_ERROR
) {
925 buffer
= &ctx
->buffers
.log_ERROR
;
928 callback
= jail
->callbacks
.log
;
929 data
= jail
->callbacks
.log_data
;
931 } else if (fd
== log_DEBUG
) {
932 buffer
= &ctx
->buffers
.log_DEBUG
;
933 priority
= LOG_DEBUG
;
935 callback
= jail
->callbacks
.log
;
936 data
= jail
->callbacks
.log_data
;
938 // Handle anything from the log pipes
939 } else if (fd
== stdout
) {
940 buffer
= &ctx
->buffers
.stdout
;
943 // Send any output to the default logger if no callback is set
944 if (ctx
->communicate
.out
) {
945 callback
= ctx
->communicate
.out
;
946 data
= ctx
->communicate
.data
;
948 callback
= jail
->callbacks
.log
;
949 data
= jail
->callbacks
.log_data
;
952 } else if (fd
== stderr
) {
953 buffer
= &ctx
->buffers
.stderr
;
956 // Send any output to the default logger if no callback is set
957 if (ctx
->communicate
.out
) {
958 callback
= ctx
->communicate
.out
;
959 data
= ctx
->communicate
.data
;
961 callback
= jail
->callbacks
.log
;
962 data
= jail
->callbacks
.log_data
;
966 DEBUG(jail
->pakfire
, "Received invalid file descriptor %d\n", fd
);
971 r
= pakfire_jail_handle_log(jail
, ctx
, priority
, fd
, buffer
, callback
, data
);
977 // Handle standard input
979 r
= pakfire_jail_stream_stdin(jail
, ctx
, fd
);
982 // Ignore if we filled up the buffer
987 ERROR(jail
->pakfire
, "Could not write to stdin: %m\n");
994 // Check if any file descriptors have been closed
996 // Remove the file descriptor
997 r
= epoll_ctl(epollfd
, EPOLL_CTL_DEL
, fd
, NULL
);
999 ERROR(jail
->pakfire
, "Could not remove closed file-descriptor %d: %m\n", fd
);
1017 int pakfire_jail_capture_stdout(struct pakfire
* pakfire
, void* data
,
1018 int priority
, const char* line
, size_t length
) {
1019 char** output
= (char**)data
;
1022 // Append everything from stdout to a buffer
1023 if (output
&& priority
== LOG_INFO
) {
1024 r
= asprintf(output
, "%s%s", (output
&& *output
) ? *output
: "", line
);
1030 // Send everything else to the default logger
1031 return pakfire_jail_default_log_callback(pakfire
, NULL
, priority
, line
, length
);
1036 // Logs all capabilities of the current process
1037 static int pakfire_jail_show_capabilities(struct pakfire_jail
* jail
) {
1040 cap_flag_value_t value_e
;
1041 cap_flag_value_t value_i
;
1042 cap_flag_value_t value_p
;
1046 pid_t pid
= getpid();
1048 // Fetch all capabilities
1049 caps
= cap_get_proc();
1051 ERROR(jail
->pakfire
, "Could not fetch capabilities: %m\n");
1056 DEBUG(jail
->pakfire
, "Capabilities of PID %d:\n", pid
);
1058 // Iterate over all capabilities
1059 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1060 name
= cap_to_name(cap
);
1062 // Fetch effective value
1063 r
= cap_get_flag(caps
, cap
, CAP_EFFECTIVE
, &value_e
);
1067 // Fetch inheritable value
1068 r
= cap_get_flag(caps
, cap
, CAP_INHERITABLE
, &value_i
);
1072 // Fetch permitted value
1073 r
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &value_p
);
1077 DEBUG(jail
->pakfire
,
1078 " %-24s : %c%c%c\n",
1080 (value_e
== CAP_SET
) ? 'e' : '-',
1081 (value_i
== CAP_SET
) ? 'i' : '-',
1082 (value_p
== CAP_SET
) ? 'p' : '-'
1102 static int pakfire_jail_set_capabilities(struct pakfire_jail
* jail
) {
1107 // Fetch capabilities
1108 caps
= cap_get_proc();
1110 ERROR(jail
->pakfire
, "Could not read capabilities: %m\n");
1115 // Walk through all capabilities
1116 for (cap_value_t cap
= 0; cap_valid(cap
); cap
++) {
1117 cap_value_t _caps
[] = { cap
};
1119 // Fetch the name of the capability
1120 name
= cap_to_name(cap
);
1122 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, _caps
, CAP_SET
);
1124 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1128 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, _caps
, CAP_SET
);
1130 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1134 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, _caps
, CAP_SET
);
1136 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1145 // Restore all capabilities
1146 r
= cap_set_proc(caps
);
1148 ERROR(jail
->pakfire
, "Restoring capabilities failed: %m\n");
1152 // Add all capabilities to the ambient set
1153 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1154 name
= cap_to_name(cap
);
1156 // Raise the capability
1157 r
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
1159 ERROR(jail
->pakfire
, "Could not set ambient capability %s: %m\n", name
);
1182 static int pakfire_jail_limit_syscalls(struct pakfire_jail
* jail
) {
1183 const int syscalls
[] = {
1184 // The kernel's keyring isn't namespaced
1187 SCMP_SYS(request_key
),
1189 // Disable userfaultfd
1190 SCMP_SYS(userfaultfd
),
1192 // Disable perf which could leak a lot of information about the host
1193 SCMP_SYS(perf_event_open
),
1199 DEBUG(jail
->pakfire
, "Applying syscall filter...\n");
1201 // Setup a syscall filter which allows everything by default
1202 scmp_filter_ctx ctx
= seccomp_init(SCMP_ACT_ALLOW
);
1204 ERROR(jail
->pakfire
, "Could not setup seccomp filter: %m\n");
1209 for (const int* syscall
= syscalls
; *syscall
; syscall
++) {
1210 r
= seccomp_rule_add(ctx
, SCMP_ACT_ERRNO(EPERM
), *syscall
, 0);
1212 ERROR(jail
->pakfire
, "Could not configure syscall %d: %m\n", *syscall
);
1217 // Load syscall filter into the kernel
1218 r
= seccomp_load(ctx
);
1220 ERROR(jail
->pakfire
, "Could not load syscall filter into the kernel: %m\n");
1226 seccomp_release(ctx
);
1233 PAKFIRE_EXPORT
int pakfire_jail_bind(struct pakfire_jail
* jail
,
1234 const char* source
, const char* target
, int flags
) {
1235 struct pakfire_jail_mountpoint
* mp
= NULL
;
1238 // Check if there is any space left
1239 if (jail
->num_mountpoints
>= MAX_MOUNTPOINTS
) {
1244 // Check for valid inputs
1245 if (!source
|| !target
) {
1250 // Select the next free slot
1251 mp
= &jail
->mountpoints
[jail
->num_mountpoints
];
1254 r
= pakfire_string_set(mp
->source
, source
);
1256 ERROR(jail
->pakfire
, "Could not copy source: %m\n");
1261 r
= pakfire_string_set(mp
->target
, target
);
1263 ERROR(jail
->pakfire
, "Could not copy target: %m\n");
1270 // Increment counter
1271 jail
->num_mountpoints
++;
1276 static int pakfire_jail_mount_networking(struct pakfire_jail
* jail
) {
1279 const char* paths
[] = {
1285 // Bind-mount all paths read-only
1286 for (const char** path
= paths
; *path
; path
++) {
1287 r
= pakfire_bind(jail
->pakfire
, *path
, NULL
, MS_RDONLY
);
1290 // Ignore if we don't have permission
1305 Mounts everything that we require in the new namespace
1307 static int pakfire_jail_mount(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1308 struct pakfire_jail_mountpoint
* mp
= NULL
;
1312 // Enable loop devices
1313 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_LOOP_DEVICES
))
1314 flags
|= PAKFIRE_MOUNT_LOOP_DEVICES
;
1316 // Mount all default stuff
1317 r
= pakfire_mount_all(jail
->pakfire
, flags
);
1321 // Mount networking stuff
1322 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1323 r
= pakfire_jail_mount_networking(jail
);
1328 // Mount all custom stuff
1329 for (unsigned int i
= 0; i
< jail
->num_mountpoints
; i
++) {
1331 mp
= &jail
->mountpoints
[i
];
1334 r
= pakfire_bind(jail
->pakfire
, mp
->source
, mp
->target
, mp
->flags
);
1339 // Log all mountpoints
1340 pakfire_mount_list(jail
->pakfire
);
1347 static int pakfire_jail_setup_loopback(struct pakfire_jail
* jail
) {
1348 struct nl_sock
* nl
= NULL
;
1349 struct nl_cache
* cache
= NULL
;
1350 struct rtnl_link
* link
= NULL
;
1351 struct rtnl_link
* change
= NULL
;
1354 DEBUG(jail
->pakfire
, "Setting up loopback...\n");
1356 // Allocate a netlink socket
1357 nl
= nl_socket_alloc();
1359 ERROR(jail
->pakfire
, "Could not allocate a netlink socket: %m\n");
1364 // Connect the socket
1365 r
= nl_connect(nl
, NETLINK_ROUTE
);
1367 ERROR(jail
->pakfire
, "Could not connect netlink socket: %s\n", nl_geterror(r
));
1371 // Allocate the netlink cache
1372 r
= rtnl_link_alloc_cache(nl
, AF_UNSPEC
, &cache
);
1374 ERROR(jail
->pakfire
, "Unable to allocate netlink cache: %s\n", nl_geterror(r
));
1378 // Fetch loopback interface
1379 link
= rtnl_link_get_by_name(cache
, "lo");
1381 ERROR(jail
->pakfire
, "Could not find lo interface. Ignoring.\n");
1386 // Allocate a new link
1387 change
= rtnl_link_alloc();
1389 ERROR(jail
->pakfire
, "Could not allocate change link\n");
1394 // Set the link to UP
1395 rtnl_link_set_flags(change
, IFF_UP
);
1397 // Apply any changes
1398 r
= rtnl_link_change(nl
, link
, change
, 0);
1400 ERROR(jail
->pakfire
, "Unable to activate loopback: %s\n", nl_geterror(r
));
1416 static int pakfire_jail_setup_uid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1417 char path
[PATH_MAX
];
1420 // Skip mapping anything when running on /
1421 if (pakfire_on_root(jail
->pakfire
))
1425 r
= pakfire_string_format(path
, "/proc/%d/uid_map", pid
);
1430 const uid_t uid
= pakfire_uid(jail
->pakfire
);
1433 const struct pakfire_subid
* subuid
= pakfire_subuid(jail
->pakfire
);
1437 /* When running as root, we will map the entire range.
1439 When running as a non-privileged user, we will map the root user inside the jail
1440 to the user's UID outside of the jail, and we will map the rest starting from one.
1445 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1446 "0 %lu %lu\n", subuid
->id
, subuid
->length
);
1448 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1449 "0 %lu 1\n1 %lu %lu\n", uid
, subuid
->id
, subuid
->length
);
1453 ERROR(jail
->pakfire
, "Could not map UIDs: %m\n");
1460 static int pakfire_jail_setup_gid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1461 char path
[PATH_MAX
];
1464 // Skip mapping anything when running on /
1465 if (pakfire_on_root(jail
->pakfire
))
1469 const gid_t gid
= pakfire_gid(jail
->pakfire
);
1472 const struct pakfire_subid
* subgid
= pakfire_subgid(jail
->pakfire
);
1477 r
= pakfire_string_format(path
, "/proc/%d/gid_map", pid
);
1483 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1484 "0 %lu %lu\n", subgid
->id
, subgid
->length
);
1486 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1487 "0 %lu 1\n%1 %lu %lu\n", gid
, subgid
->id
, subgid
->length
);
1491 ERROR(jail
->pakfire
, "Could not map GIDs: %m\n");
1498 static int pakfire_jail_setgroups(struct pakfire_jail
* jail
, pid_t pid
) {
1499 char path
[PATH_MAX
];
1503 r
= pakfire_string_format(path
, "/proc/%d/setgroups", pid
);
1507 // Open file for writing
1508 FILE* f
= fopen(path
, "w");
1510 ERROR(jail
->pakfire
, "Could not open %s for writing: %m\n", path
);
1515 int bytes_written
= fprintf(f
, "deny\n");
1516 if (bytes_written
<= 0) {
1517 ERROR(jail
->pakfire
, "Could not write to %s: %m\n", path
);
1524 ERROR(jail
->pakfire
, "Could not close %s: %m\n", path
);
1535 static int pakfire_jail_send_signal(struct pakfire_jail
* jail
, int fd
) {
1536 const uint64_t val
= 1;
1539 DEBUG(jail
->pakfire
, "Sending signal...\n");
1541 // Write to the file descriptor
1542 ssize_t bytes_written
= write(fd
, &val
, sizeof(val
));
1543 if (bytes_written
< 0 || (size_t)bytes_written
< sizeof(val
)) {
1544 ERROR(jail
->pakfire
, "Could not send signal: %m\n");
1548 // Close the file descriptor
1554 static int pakfire_jail_wait_for_signal(struct pakfire_jail
* jail
, int fd
) {
1558 DEBUG(jail
->pakfire
, "Waiting for signal...\n");
1560 ssize_t bytes_read
= read(fd
, &val
, sizeof(val
));
1561 if (bytes_read
< 0 || (size_t)bytes_read
< sizeof(val
)) {
1562 ERROR(jail
->pakfire
, "Error waiting for signal: %m\n");
1566 // Close the file descriptor
1573 Performs the initialisation that needs to happen in the parent part
1575 static int pakfire_jail_parent(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1578 // Setup UID mapping
1579 r
= pakfire_jail_setup_uid_mapping(jail
, ctx
->pid
);
1583 // Write "deny" to /proc/PID/setgroups
1584 r
= pakfire_jail_setgroups(jail
, ctx
->pid
);
1588 // Setup GID mapping
1589 r
= pakfire_jail_setup_gid_mapping(jail
, ctx
->pid
);
1593 // Parent has finished initialisation
1594 DEBUG(jail
->pakfire
, "Parent has finished initialization\n");
1596 // Send signal to client
1597 r
= pakfire_jail_send_signal(jail
, ctx
->completed_fd
);
1604 static int pakfire_jail_switch_root(struct pakfire_jail
* jail
, const char* root
) {
1607 // Change to the new root
1610 ERROR(jail
->pakfire
, "chdir(%s) failed: %m\n", root
);
1615 r
= pivot_root(".", ".");
1617 ERROR(jail
->pakfire
, "Failed changing into the new root directory %s: %m\n", root
);
1621 // Umount the old root
1622 r
= umount2(".", MNT_DETACH
);
1624 ERROR(jail
->pakfire
, "Could not umount the old root filesystem: %m\n");
1631 static int pakfire_jail_child(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
1632 const char* argv
[]) {
1635 // Redirect any logging to our log pipe
1636 pakfire_set_log_callback(jail
->pakfire
, pakfire_jail_log
, &ctx
->pipes
);
1639 pid_t pid
= getpid();
1641 DEBUG(jail
->pakfire
, "Launched child process in jail with PID %d\n", pid
);
1643 // Wait for the parent to finish initialization
1644 r
= pakfire_jail_wait_for_signal(jail
, ctx
->completed_fd
);
1649 r
= prctl(PR_SET_PDEATHSIG
, SIGKILL
, 0, 0, 0);
1651 ERROR(jail
->pakfire
, "Could not configure to die with parent: %m\n");
1655 // Make this process dumpable
1656 r
= prctl (PR_SET_DUMPABLE
, 1, 0, 0, 0);
1658 ERROR(jail
->pakfire
, "Could not make the process dumpable: %m\n");
1662 // Don't drop any capabilities on setuid()
1663 r
= prctl(PR_SET_KEEPCAPS
, 1);
1665 ERROR(jail
->pakfire
, "Could not set PR_SET_KEEPCAPS: %m\n");
1670 uid_t uid
= getuid();
1671 gid_t gid
= getgid();
1674 uid_t euid
= geteuid();
1675 gid_t egid
= getegid();
1677 DEBUG(jail
->pakfire
, " UID: %d (effective %d)\n", uid
, euid
);
1678 DEBUG(jail
->pakfire
, " GID: %d (effective %d)\n", gid
, egid
);
1680 // Check if we are (effectively running as root)
1681 if (uid
|| gid
|| euid
|| egid
) {
1682 ERROR(jail
->pakfire
, "Child process is not running as root\n");
1686 const char* root
= pakfire_get_path(jail
->pakfire
);
1687 const char* arch
= pakfire_get_effective_arch(jail
->pakfire
);
1689 // Change mount propagation to slave to receive anything from the parent namespace
1690 r
= pakfire_mount_change_propagation(jail
->pakfire
, MS_SLAVE
, "/");
1694 // Make root a mountpoint in the new mount namespace
1695 r
= pakfire_mount_make_mounpoint(jail
->pakfire
, root
);
1699 // Change mount propagation to private
1700 r
= pakfire_mount_change_propagation(jail
->pakfire
, MS_PRIVATE
, root
);
1704 // Change root (unless root is /)
1705 if (!pakfire_on_root(jail
->pakfire
)) {
1707 r
= pakfire_jail_mount(jail
, ctx
);
1712 r
= pakfire_jail_switch_root(jail
, root
);
1718 unsigned long persona
= pakfire_arch_personality(arch
);
1720 r
= personality(persona
);
1722 ERROR(jail
->pakfire
, "Could not set personality (%x)\n", (unsigned int)persona
);
1728 if (!pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1729 r
= pakfire_jail_setup_loopback(jail
);
1736 DEBUG(jail
->pakfire
, "Setting nice level to %d\n", jail
->nice
);
1738 r
= setpriority(PRIO_PROCESS
, pid
, jail
->nice
);
1740 ERROR(jail
->pakfire
, "Could not set nice level: %m\n");
1745 // Close other end of log pipes
1746 close(ctx
->pipes
.log_INFO
[0]);
1747 close(ctx
->pipes
.log_ERROR
[0]);
1749 close(ctx
->pipes
.log_DEBUG
[0]);
1750 #endif /* ENABLE_DEBUG */
1752 // Connect standard input
1753 if (ctx
->pipes
.stdin
[0] >= 0) {
1754 r
= dup2(ctx
->pipes
.stdin
[0], STDIN_FILENO
);
1756 ERROR(jail
->pakfire
, "Could not connect fd %d to stdin: %m\n",
1757 ctx
->pipes
.stdin
[0]);
1763 // Connect standard output and error
1764 if (ctx
->pipes
.stdout
[1] >= 0 && ctx
->pipes
.stderr
[1] >= 0) {
1765 r
= dup2(ctx
->pipes
.stdout
[1], STDOUT_FILENO
);
1767 ERROR(jail
->pakfire
, "Could not connect fd %d to stdout: %m\n",
1768 ctx
->pipes
.stdout
[1]);
1773 r
= dup2(ctx
->pipes
.stderr
[1], STDERR_FILENO
);
1775 ERROR(jail
->pakfire
, "Could not connect fd %d to stderr: %m\n",
1776 ctx
->pipes
.stderr
[1]);
1781 // Close the pipe (as we have moved the original file descriptors)
1782 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdin
);
1783 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdout
);
1784 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stderr
);
1787 // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
1788 r
= pakfire_rlimit_reset_nofile(jail
->pakfire
);
1793 r
= pakfire_jail_set_capabilities(jail
);
1797 // Show capabilities
1798 r
= pakfire_jail_show_capabilities(jail
);
1803 r
= pakfire_jail_limit_syscalls(jail
);
1807 DEBUG(jail
->pakfire
, "Child process initialization done\n");
1808 DEBUG(jail
->pakfire
, "Launching command:\n");
1811 for (unsigned int i
= 0; argv
[i
]; i
++)
1812 DEBUG(jail
->pakfire
, " argv[%d] = %s\n", i
, argv
[i
]);
1815 r
= execvpe(argv
[0], (char**)argv
, jail
->env
);
1817 // Translate errno into regular exit code
1820 // Ignore if the command doesn't exist
1821 if (ctx
->flags
& PAKFIRE_JAIL_NOENT_OK
)
1832 ERROR(jail
->pakfire
, "Could not execve(%s): %m\n", argv
[0]);
1835 // We should not get here
1839 // Run a command in the jail
1840 static int __pakfire_jail_exec(struct pakfire_jail
* jail
, const char* argv
[],
1841 const int interactive
,
1842 pakfire_jail_communicate_in communicate_in
,
1843 pakfire_jail_communicate_out communicate_out
,
1844 void* data
, int flags
) {
1848 // Check if argv is valid
1849 if (!argv
|| !argv
[0]) {
1854 // Initialize context for this call
1855 struct pakfire_jail_exec ctx
= {
1859 .stdin
= { -1, -1 },
1860 .stdout
= { -1, -1 },
1861 .stderr
= { -1, -1 },
1865 .in
= communicate_in
,
1866 .out
= communicate_out
,
1873 DEBUG(jail
->pakfire
, "Executing jail...\n");
1875 // Enable networking in interactive mode
1877 ctx
.flags
|= PAKFIRE_JAIL_HAS_NETWORKING
;
1880 Setup a file descriptor which can be used to notify the client that the parent
1881 has completed configuration.
1883 ctx
.completed_fd
= eventfd(0, EFD_CLOEXEC
);
1884 if (ctx
.completed_fd
< 0) {
1885 ERROR(jail
->pakfire
, "eventfd() failed: %m\n");
1889 // Create pipes to communicate with child process if we are not running interactively
1891 // stdin (only if callback is set)
1892 if (ctx
.communicate
.in
) {
1893 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdin
, 0);
1899 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdout
, 0);
1904 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stderr
, 0);
1909 // Setup pipes for logging
1911 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_INFO
, O_CLOEXEC
);
1916 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_ERROR
, O_CLOEXEC
);
1922 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_DEBUG
, O_CLOEXEC
);
1925 #endif /* ENABLE_DEBUG */
1927 // Configure child process
1928 struct clone_args args
= {
1938 .exit_signal
= SIGCHLD
,
1939 .pidfd
= (long long unsigned int)&ctx
.pidfd
,
1942 // Launch the process in a cgroup that is a leaf of the configured cgroup
1944 args
.flags
|= CLONE_INTO_CGROUP
;
1947 const char* uuid
= pakfire_jail_uuid(jail
);
1949 // Create a temporary cgroup
1950 r
= pakfire_cgroup_child(&ctx
.cgroup
, jail
->cgroup
, uuid
, 0);
1952 ERROR(jail
->pakfire
, "Could not create cgroup for jail: %m\n");
1956 // Clone into this cgroup
1957 args
.cgroup
= pakfire_cgroup_fd(ctx
.cgroup
);
1961 if (!pakfire_jail_exec_has_flag(&ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1962 args
.flags
|= CLONE_NEWNET
;
1965 // Fork this process
1966 ctx
.pid
= clone3(&args
, sizeof(args
));
1968 ERROR(jail
->pakfire
, "Could not clone: %m\n");
1972 } else if (ctx
.pid
== 0) {
1973 r
= pakfire_jail_child(jail
, &ctx
, argv
);
1978 r
= pakfire_jail_parent(jail
, &ctx
);
1982 DEBUG(jail
->pakfire
, "Waiting for PID %d to finish its work\n", ctx
.pid
);
1984 // Read output of the child process
1985 r
= pakfire_jail_wait(jail
, &ctx
);
1989 // Handle exit status
1990 switch (ctx
.status
.si_code
) {
1992 DEBUG(jail
->pakfire
, "The child process exited with code %d\n",
1993 ctx
.status
.si_status
);
1996 exit
= ctx
.status
.si_status
;
2000 ERROR(jail
->pakfire
, "The child process was killed\n");
2005 ERROR(jail
->pakfire
, "The child process terminated abnormally\n");
2008 // Log anything else
2010 ERROR(jail
->pakfire
, "Unknown child exit code: %d\n", ctx
.status
.si_code
);
2015 // Destroy the temporary cgroup (if any)
2017 // Read cgroup stats
2018 r
= pakfire_cgroup_stat(ctx
.cgroup
, &ctx
.cgroup_stats
);
2020 ERROR(jail
->pakfire
, "Could not read cgroup stats: %m\n");
2022 pakfire_cgroup_stat_dump(ctx
.cgroup
, &ctx
.cgroup_stats
);
2025 pakfire_cgroup_destroy(ctx
.cgroup
);
2026 pakfire_cgroup_unref(ctx
.cgroup
);
2029 // Close any file descriptors
2030 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdin
);
2031 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdout
);
2032 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stderr
);
2035 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_INFO
);
2036 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_ERROR
);
2037 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_DEBUG
);
2042 PAKFIRE_EXPORT
int pakfire_jail_exec(
2043 struct pakfire_jail
* jail
,
2045 pakfire_jail_communicate_in callback_in
,
2046 pakfire_jail_communicate_out callback_out
,
2047 void* data
, int flags
) {
2048 return __pakfire_jail_exec(jail
, argv
, 0, callback_in
, callback_out
, data
, flags
);
2051 static int pakfire_jail_exec_interactive(
2052 struct pakfire_jail
* jail
, const char* argv
[], int flags
) {
2055 // Setup interactive stuff
2056 r
= pakfire_jail_setup_interactive_env(jail
);
2060 return __pakfire_jail_exec(jail
, argv
, 1, NULL
, NULL
, NULL
, flags
);
2063 int pakfire_jail_exec_script(struct pakfire_jail
* jail
,
2067 pakfire_jail_communicate_in callback_in
,
2068 pakfire_jail_communicate_out callback_out
,
2070 char path
[PATH_MAX
];
2071 const char** argv
= NULL
;
2075 const char* root
= pakfire_get_path(jail
->pakfire
);
2077 // Write the scriptlet to disk
2078 r
= pakfire_path_join(path
, root
, PAKFIRE_TMP_DIR
"/pakfire-script.XXXXXX");
2082 // Create a temporary file
2083 f
= pakfire_mktemp(path
, 0700);
2085 ERROR(jail
->pakfire
, "Could not create temporary file: %m\n");
2089 DEBUG(jail
->pakfire
, "Writing script to %s:\n%.*s\n", path
, (int)size
, script
);
2092 r
= fprintf(f
, "%s", script
);
2094 ERROR(jail
->pakfire
, "Could not write script to file %s: %m\n", path
);
2101 ERROR(jail
->pakfire
, "Could not close script file %s: %m\n", path
);
2107 // Count how many arguments were passed
2108 unsigned int argc
= 1;
2110 for (const char** arg
= args
; *arg
; arg
++)
2114 argv
= calloc(argc
+ 1, sizeof(*argv
));
2116 ERROR(jail
->pakfire
, "Could not allocate argv: %m\n");
2121 argv
[0] = (root
) ? pakfire_path_relpath(root
, path
) : path
;
2124 for (unsigned int i
= 1; i
< argc
; i
++)
2125 argv
[i
] = args
[i
-1];
2128 r
= pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, 0);
2136 // Remove script from disk
2144 A convenience function that creates a new jail, runs the given command and destroys
2147 int pakfire_jail_run(struct pakfire
* pakfire
, const char* argv
[], int flags
, char** output
) {
2148 struct pakfire_jail
* jail
= NULL
;
2151 // Create a new jail
2152 r
= pakfire_jail_create(&jail
, pakfire
);
2156 // Execute the command
2157 r
= pakfire_jail_exec(jail
, argv
, NULL
, pakfire_jail_capture_stdout
, output
, 0);
2161 pakfire_jail_unref(jail
);
2166 int pakfire_jail_run_script(struct pakfire
* pakfire
,
2167 const char* script
, const size_t length
, const char* argv
[], int flags
) {
2168 struct pakfire_jail
* jail
= NULL
;
2171 // Create a new jail
2172 r
= pakfire_jail_create(&jail
, pakfire
);
2176 // Execute the command
2177 r
= pakfire_jail_exec_script(jail
, script
, length
, argv
, NULL
, NULL
, NULL
);
2181 pakfire_jail_unref(jail
);
2186 int pakfire_jail_shell(struct pakfire_jail
* jail
) {
2189 const char* argv
[] = {
2190 "/bin/bash", "--login", NULL
,
2193 // Execute /bin/bash
2194 r
= pakfire_jail_exec_interactive(jail
, argv
, 0);
2200 // Ignore any return codes from the shell
2204 static int pakfire_jail_run_if_possible(struct pakfire
* pakfire
, const char** argv
) {
2205 char path
[PATH_MAX
];
2208 r
= pakfire_path(pakfire
, path
, "%s", *argv
);
2212 // Check if the file is executable
2213 r
= access(path
, X_OK
);
2215 DEBUG(pakfire
, "%s is not executable. Skipping...\n", *argv
);
2219 return pakfire_jail_run(pakfire
, argv
, 0, NULL
);
2222 int pakfire_jail_ldconfig(struct pakfire
* pakfire
) {
2223 const char* argv
[] = {
2228 return pakfire_jail_run_if_possible(pakfire
, argv
);
2231 int pakfire_jail_run_systemd_tmpfiles(struct pakfire
* pakfire
) {
2232 const char* argv
[] = {
2233 "/usr/bin/systemd-tmpfiles",
2238 return pakfire_jail_run_if_possible(pakfire
, argv
);