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_log_buffer
{
116 char data
[BUFFER_SIZE
];
120 struct pakfire_jail_exec
{
123 // PID (of the child)
127 // Process status (from waitid)
130 // FD to notify the client that the parent has finished initialization
134 struct pakfire_jail_pipes
{
146 struct pakfire_jail_communicate
{
147 pakfire_jail_communicate_in in
;
148 pakfire_jail_communicate_out out
;
153 struct pakfire_jail_buffers
{
154 struct pakfire_log_buffer stdout
;
155 struct pakfire_log_buffer stderr
;
158 struct pakfire_log_buffer log_INFO
;
159 struct pakfire_log_buffer log_ERROR
;
160 struct pakfire_log_buffer log_DEBUG
;
163 struct pakfire_cgroup
* cgroup
;
164 struct pakfire_cgroup_stats cgroup_stats
;
167 static int clone3(struct clone_args
* args
, size_t size
) {
168 return syscall(__NR_clone3
, args
, size
);
171 static int pidfd_send_signal(int pidfd
, int sig
, siginfo_t
* info
, unsigned int flags
) {
172 return syscall(SYS_pidfd_send_signal
, pidfd
, sig
, info
, flags
);
175 static int pakfire_jail_exec_has_flag(
176 const struct pakfire_jail_exec
* ctx
, const enum pakfire_jail_exec_flags flag
) {
177 return ctx
->flags
& flag
;
180 static void pakfire_jail_free(struct pakfire_jail
* jail
) {
181 DEBUG(jail
->pakfire
, "Freeing jail at %p\n", jail
);
184 for (unsigned int i
= 0; jail
->env
[i
]; i
++)
188 pakfire_cgroup_unref(jail
->cgroup
);
190 pakfire_unref(jail
->pakfire
);
195 Passes any log messages on to the default pakfire log callback
197 static int pakfire_jail_default_log_callback(struct pakfire
* pakfire
, void* data
,
198 int priority
, const char* line
, size_t length
) {
201 INFO(pakfire
, "%s", line
);
205 ERROR(pakfire
, "%s", line
);
210 DEBUG(pakfire
, "%s", line
);
218 static const char* pakfire_jail_uuid(struct pakfire_jail
* jail
) {
220 uuid_unparse_lower(jail
->uuid
, jail
->__uuid
);
225 static int pakfire_jail_setup_interactive_env(struct pakfire_jail
* jail
) {
227 int r
= pakfire_jail_set_env(jail
, "PS1", "pakfire-jail \\w> ");
232 char* TERM
= secure_getenv("TERM");
234 r
= pakfire_jail_set_env(jail
, "TERM", TERM
);
240 char* LANG
= secure_getenv("LANG");
242 r
= pakfire_jail_set_env(jail
, "LANG", LANG
);
250 PAKFIRE_EXPORT
int pakfire_jail_create(struct pakfire_jail
** jail
, struct pakfire
* pakfire
) {
253 const char* arch
= pakfire_get_arch(pakfire
);
255 // Allocate a new jail
256 struct pakfire_jail
* j
= calloc(1, sizeof(*j
));
261 j
->pakfire
= pakfire_ref(pakfire
);
263 // Initialize reference counter
266 // Generate a random UUID
267 uuid_generate_random(j
->uuid
);
269 DEBUG(j
->pakfire
, "Allocated new jail at %p\n", j
);
271 // Set default environment
272 for (const struct environ
* e
= ENV
; e
->key
; e
++) {
273 r
= pakfire_jail_set_env(j
, e
->key
, e
->val
);
278 // Enable all CPU features that CPU has to offer
279 if (!pakfire_arch_supported_by_host(arch
)) {
280 r
= pakfire_jail_set_env(j
, "QEMU_CPU", "max");
285 // Set container UUID
286 r
= pakfire_jail_set_env(j
, "container_uuid", pakfire_jail_uuid(j
));
290 // Disable systemctl to talk to systemd
291 if (!pakfire_on_root(j
->pakfire
)) {
292 r
= pakfire_jail_set_env(j
, "SYSTEMD_OFFLINE", "1");
302 pakfire_jail_free(j
);
307 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_ref(struct pakfire_jail
* jail
) {
313 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_unref(struct pakfire_jail
* jail
) {
314 if (--jail
->nrefs
> 0)
317 pakfire_jail_free(jail
);
323 PAKFIRE_EXPORT
int pakfire_jail_nice(struct pakfire_jail
* jail
, int nice
) {
324 // Check if nice level is in range
325 if (nice
< -19 || nice
> 20) {
336 int pakfire_jail_set_cgroup(struct pakfire_jail
* jail
, struct pakfire_cgroup
* cgroup
) {
337 // Free any previous cgroup
339 pakfire_cgroup_unref(jail
->cgroup
);
343 // Set any new cgroup
345 DEBUG(jail
->pakfire
, "Setting cgroup %p\n", cgroup
);
347 jail
->cgroup
= pakfire_cgroup_ref(cgroup
);
356 // Returns the length of the environment
357 static unsigned int pakfire_jail_env_length(struct pakfire_jail
* jail
) {
360 // Count everything in the environment
361 for (char** e
= jail
->env
; *e
; e
++)
367 // Finds an existing environment variable and returns its index or -1 if not found
368 static int pakfire_jail_find_env(struct pakfire_jail
* jail
, const char* key
) {
374 const size_t length
= strlen(key
);
376 for (unsigned int i
= 0; jail
->env
[i
]; i
++) {
377 if ((pakfire_string_startswith(jail
->env
[i
], key
)
378 && *(jail
->env
[i
] + length
) == '=')) {
387 // Returns the value of an environment variable or NULL
388 PAKFIRE_EXPORT
const char* pakfire_jail_get_env(struct pakfire_jail
* jail
,
390 int i
= pakfire_jail_find_env(jail
, key
);
394 return jail
->env
[i
] + strlen(key
) + 1;
397 // Sets an environment variable
398 PAKFIRE_EXPORT
int pakfire_jail_set_env(struct pakfire_jail
* jail
,
399 const char* key
, const char* value
) {
400 // Find the index where to write this value to
401 int i
= pakfire_jail_find_env(jail
, key
);
403 i
= pakfire_jail_env_length(jail
);
405 // Return -ENOSPC when the environment is full
406 if (i
>= ENVIRON_SIZE
) {
411 // Free any previous value
415 // Format and set environment variable
416 asprintf(&jail
->env
[i
], "%s=%s", key
, value
);
418 DEBUG(jail
->pakfire
, "Set environment variable: %s\n", jail
->env
[i
]);
423 // Imports an environment
424 PAKFIRE_EXPORT
int pakfire_jail_import_env(struct pakfire_jail
* jail
, const char* env
[]) {
432 // Copy environment variables
433 for (unsigned int i
= 0; env
[i
]; i
++) {
434 r
= pakfire_string_partition(env
[i
], "=", &key
, &val
);
439 r
= pakfire_jail_set_env(jail
, key
, val
);
456 PAKFIRE_EXPORT
int pakfire_jail_set_timeout(
457 struct pakfire_jail
* jail
, unsigned int timeout
) {
459 jail
->timeout
.it_value
.tv_sec
= timeout
;
462 DEBUG(jail
->pakfire
, "Timeout set to %d second(s)\n", timeout
);
464 DEBUG(jail
->pakfire
, "Timeout disabled\n");
469 static int pakfire_jail_create_timer(struct pakfire_jail
* jail
) {
472 // Nothing to do if no timeout has been set
473 if (!jail
->timeout
.it_value
.tv_sec
)
476 // Create a new timer
477 const int fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
479 ERROR(jail
->pakfire
, "Could not create timer: %m\n");
484 r
= timerfd_settime(fd
, 0, &jail
->timeout
, NULL
);
486 ERROR(jail
->pakfire
, "Could not arm timer: %m\n");
501 static int pakfire_jail_handle_signals(struct pakfire_jail
* jail
) {
506 sigaddset(&mask
, SIGINT
);
509 r
= sigprocmask(SIG_BLOCK
, &mask
, NULL
);
511 ERROR(jail
->pakfire
, "Failed to block signals: %m\n");
515 // Create a file descriptor
516 r
= signalfd(-1, &mask
, SFD_NONBLOCK
|SFD_CLOEXEC
);
518 ERROR(jail
->pakfire
, "Failed to create signalfd: %m\n");
526 This function replaces any logging in the child process.
528 All log messages will be sent to the parent process through their respective pipes.
530 static void pakfire_jail_log(void* data
, int priority
, const char* file
,
531 int line
, const char* fn
, const char* format
, va_list args
) {
532 struct pakfire_jail_pipes
* pipes
= (struct pakfire_jail_pipes
*)data
;
537 fd
= pipes
->log_INFO
[1];
541 fd
= pipes
->log_ERROR
[1];
546 fd
= pipes
->log_DEBUG
[1];
548 #endif /* ENABLE_DEBUG */
550 // Ignore any messages of an unknown priority
555 // Send the log message
557 vdprintf(fd
, format
, args
);
560 static int pakfire_jail_log_buffer_is_full(const struct pakfire_log_buffer
* buffer
) {
561 return (sizeof(buffer
->data
) == buffer
->used
);
565 This function reads as much data as it can from the file descriptor.
566 If it finds a whole line in it, it will send it to the logger and repeat the process.
567 If not newline character is found, it will try to read more data until it finds one.
569 static int pakfire_jail_handle_log(struct pakfire_jail
* jail
,
570 struct pakfire_jail_exec
* ctx
, int priority
, int fd
,
571 struct pakfire_log_buffer
* buffer
, pakfire_jail_communicate_out callback
, void* data
) {
572 char line
[BUFFER_SIZE
+ 1];
574 // Fill up buffer from fd
575 if (buffer
->used
< sizeof(buffer
->data
)) {
576 ssize_t bytes_read
= read(fd
, buffer
->data
+ buffer
->used
,
577 sizeof(buffer
->data
) - buffer
->used
);
580 if (bytes_read
< 0) {
581 ERROR(jail
->pakfire
, "Could not read from fd %d: %m\n", fd
);
585 // Update buffer size
586 buffer
->used
+= bytes_read
;
589 // See if we have any lines that we can write
590 while (buffer
->used
) {
591 // Search for the end of the first line
592 char* eol
= memchr(buffer
->data
, '\n', buffer
->used
);
596 // If the buffer is full, we send the content to the logger and try again
597 // This should not happen in practise
598 if (pakfire_jail_log_buffer_is_full(buffer
)) {
599 DEBUG(jail
->pakfire
, "Logging buffer is full. Sending all content\n");
601 eol
= buffer
->data
+ sizeof(buffer
->data
) - 1;
603 // Otherwise we might have only read parts of the output
608 // Find the length of the string
609 size_t length
= eol
- buffer
->data
+ 1;
611 // Copy the line into the buffer
612 memcpy(line
, buffer
->data
, length
);
614 // Terminate the string
619 int r
= callback(jail
->pakfire
, data
, priority
, line
, length
);
621 ERROR(jail
->pakfire
, "The logging callback returned an error: %d\n", r
);
626 // Remove line from buffer
627 memmove(buffer
->data
, buffer
->data
+ length
, buffer
->used
- length
);
628 buffer
->used
-= length
;
634 static int pakfire_jail_stream_stdin(struct pakfire_jail
* jail
,
635 struct pakfire_jail_exec
* ctx
, const int fd
) {
638 // Nothing to do if there is no stdin callback set
639 if (!ctx
->communicate
.in
) {
640 DEBUG(jail
->pakfire
, "Callback for standard input is not set\n");
644 // Skip if the writing pipe has already been closed
645 if (!ctx
->pipes
.stdin
[1])
648 DEBUG(jail
->pakfire
, "Streaming standard input...\n");
650 // Calling the callback
651 r
= ctx
->communicate
.in(jail
->pakfire
, ctx
->communicate
.data
, fd
);
653 DEBUG(jail
->pakfire
, "Standard input callback finished: %d\n", r
);
655 // The callback signaled that it has written everything
657 DEBUG(jail
->pakfire
, "Closing standard input pipe\n");
659 // Close the file-descriptor
662 // Reset the file-descriptor so it won't be closed again later
663 ctx
->pipes
.stdin
[1] = 0;
672 static int pakfire_jail_setup_pipe(struct pakfire_jail
* jail
, int (*fds
)[2], const int flags
) {
673 int r
= pipe2(*fds
, flags
);
675 ERROR(jail
->pakfire
, "Could not setup pipe: %m\n");
682 static void pakfire_jail_close_pipe(struct pakfire_jail
* jail
, int fds
[2]) {
683 for (unsigned int i
= 0; i
< 2; i
++)
689 This is a convenience function to fetch the reading end of a pipe and
690 closes the write end.
692 static int pakfire_jail_get_pipe_to_read(struct pakfire_jail
* jail
, int (*fds
)[2]) {
693 // Give the variables easier names to avoid confusion
694 int* fd_read
= &(*fds
)[0];
695 int* fd_write
= &(*fds
)[1];
697 // Close the write end of the pipe
703 // Return the read end
707 static int pakfire_jail_get_pipe_to_write(struct pakfire_jail
* jail
, int (*fds
)[2]) {
708 // Give the variables easier names to avoid confusion
709 int* fd_read
= &(*fds
)[0];
710 int* fd_write
= &(*fds
)[1];
712 // Close the read end of the pipe
718 // Return the write end
722 static int pakfire_jail_wait(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
724 struct epoll_event ev
;
725 struct epoll_event events
[EPOLL_MAX_EVENTS
];
726 struct signalfd_siginfo siginfo
;
730 // Fetch file descriptors from context
731 const int stdin
= pakfire_jail_get_pipe_to_write(jail
, &ctx
->pipes
.stdin
);
732 const int stdout
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stdout
);
733 const int stderr
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stderr
);
734 const int pidfd
= ctx
->pidfd
;
737 const int timerfd
= pakfire_jail_create_timer(jail
);
740 const int log_INFO
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_INFO
);
741 const int log_ERROR
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_ERROR
);
742 const int log_DEBUG
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_DEBUG
);
745 const int signalfd
= pakfire_jail_handle_signals(jail
);
747 // Make a list of all file descriptors we are interested in
749 stdin
, stdout
, stderr
, pidfd
, timerfd
, signalfd
, log_INFO
, log_ERROR
, log_DEBUG
,
753 epollfd
= epoll_create1(0);
755 ERROR(jail
->pakfire
, "Could not initialize epoll(): %m\n");
760 // Turn file descriptors into non-blocking mode and add them to epoll()
761 for (unsigned int i
= 0; i
< sizeof(fds
) / sizeof(*fds
); i
++) {
764 // Skip fds which were not initialized
768 ev
.events
= EPOLLHUP
;
771 ev
.events
|= EPOLLOUT
;
773 ev
.events
|= EPOLLIN
;
776 int flags
= fcntl(fd
, F_GETFL
, 0);
778 // Set modified flags
779 if (fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
) < 0) {
781 "Could not set file descriptor %d into non-blocking mode: %m\n", fd
);
788 if (epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fd
, &ev
) < 0) {
789 ERROR(jail
->pakfire
, "Could not add file descriptor %d to epoll(): %m\n", fd
);
797 // Loop for as long as the process is alive
799 int num
= epoll_wait(epollfd
, events
, EPOLL_MAX_EVENTS
, -1);
801 // Ignore if epoll_wait() has been interrupted
805 ERROR(jail
->pakfire
, "epoll_wait() failed: %m\n");
811 for (int i
= 0; i
< num
; i
++) {
812 int e
= events
[i
].events
;
813 int fd
= events
[i
].data
.fd
;
815 struct pakfire_log_buffer
* buffer
= NULL
;
816 pakfire_jail_communicate_out callback
= NULL
;
820 // Check if there is any data to be read
822 // Handle any changes to the PIDFD
824 // Call waidid() and store the result
825 r
= waitid(P_PIDFD
, ctx
->pidfd
, &ctx
->status
, WEXITED
);
827 ERROR(jail
->pakfire
, "waitid() failed: %m\n");
831 // Mark that we have ended so that we will process the remaining
832 // events from epoll() now, but won't restart the outer loop.
836 // Handle timer events
837 } else if (fd
== timerfd
) {
838 DEBUG(jail
->pakfire
, "Timer event received\n");
841 r
= read(timerfd
, garbage
, sizeof(garbage
));
843 ERROR(jail
->pakfire
, "Could not disarm timer: %m\n");
848 // Terminate the process if it hasn't already ended
850 DEBUG(jail
->pakfire
, "Terminating process...\n");
852 // Send SIGTERM to the process
853 r
= pidfd_send_signal(pidfd
, SIGKILL
, NULL
, 0);
855 ERROR(jail
->pakfire
, "Could not kill process: %m\n");
860 // There is nothing else to do
864 } else if (fd
== signalfd
) {
866 r
= read(signalfd
, &siginfo
, sizeof(siginfo
));
868 ERROR(jail
->pakfire
, "Could not read signal: %m\n");
872 DEBUG(jail
->pakfire
, "Received signal %d\n", siginfo
.ssi_signo
);
875 switch (siginfo
.ssi_signo
) {
876 // Pass SIGINT down to the child process
878 r
= pidfd_send_signal(pidfd
, siginfo
.ssi_signo
, NULL
, 0);
880 ERROR(jail
->pakfire
, "Could not send signal to process: %m\n");
886 ERROR(jail
->pakfire
, "Received unhandled signal %d\n",
891 // Don't fall through to log processing
894 // Handle logging messages
895 } else if (fd
== log_INFO
) {
896 buffer
= &ctx
->buffers
.log_INFO
;
899 callback
= pakfire_jail_default_log_callback
;
901 } else if (fd
== log_ERROR
) {
902 buffer
= &ctx
->buffers
.log_ERROR
;
905 callback
= pakfire_jail_default_log_callback
;
907 } else if (fd
== log_DEBUG
) {
908 buffer
= &ctx
->buffers
.log_DEBUG
;
909 priority
= LOG_DEBUG
;
911 callback
= pakfire_jail_default_log_callback
;
913 // Handle anything from the log pipes
914 } else if (fd
== stdout
) {
915 buffer
= &ctx
->buffers
.stdout
;
918 callback
= ctx
->communicate
.out
;
919 data
= ctx
->communicate
.data
;
921 } else if (fd
== stderr
) {
922 buffer
= &ctx
->buffers
.stderr
;
925 callback
= ctx
->communicate
.out
;
926 data
= ctx
->communicate
.data
;
929 DEBUG(jail
->pakfire
, "Received invalid file descriptor %d\n", fd
);
934 r
= pakfire_jail_handle_log(jail
, ctx
, priority
, fd
, buffer
, callback
, data
);
940 // Handle standard input
942 r
= pakfire_jail_stream_stdin(jail
, ctx
, fd
);
945 // Ignore if we filled up the buffer
950 ERROR(jail
->pakfire
, "Could not write to stdin: %m\n");
957 // Check if any file descriptors have been closed
959 // Remove the file descriptor
960 r
= epoll_ctl(epollfd
, EPOLL_CTL_DEL
, fd
, NULL
);
962 ERROR(jail
->pakfire
, "Could not remove closed file-descriptor %d: %m\n", fd
);
980 int pakfire_jail_capture_stdout(struct pakfire
* pakfire
, void* data
,
981 int priority
, const char* line
, size_t length
) {
982 char** output
= (char**)data
;
985 // Append everything from stdout to a buffer
986 if (output
&& priority
== LOG_INFO
) {
987 r
= asprintf(output
, "%s%s", (output
&& *output
) ? *output
: "", line
);
993 // Send everything else to the default logger
994 return pakfire_jail_default_log_callback(pakfire
, NULL
, priority
, line
, length
);
999 // Logs all capabilities of the current process
1000 static int pakfire_jail_show_capabilities(struct pakfire_jail
* jail
) {
1003 cap_flag_value_t value_e
;
1004 cap_flag_value_t value_i
;
1005 cap_flag_value_t value_p
;
1009 pid_t pid
= getpid();
1011 // Fetch all capabilities
1012 caps
= cap_get_proc();
1014 ERROR(jail
->pakfire
, "Could not fetch capabilities: %m\n");
1019 DEBUG(jail
->pakfire
, "Capabilities of PID %d:\n", pid
);
1021 // Iterate over all capabilities
1022 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1023 name
= cap_to_name(cap
);
1025 // Fetch effective value
1026 r
= cap_get_flag(caps
, cap
, CAP_EFFECTIVE
, &value_e
);
1030 // Fetch inheritable value
1031 r
= cap_get_flag(caps
, cap
, CAP_INHERITABLE
, &value_i
);
1035 // Fetch permitted value
1036 r
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &value_p
);
1040 DEBUG(jail
->pakfire
,
1041 " %-24s : %c%c%c\n",
1043 (value_e
== CAP_SET
) ? 'e' : '-',
1044 (value_i
== CAP_SET
) ? 'i' : '-',
1045 (value_p
== CAP_SET
) ? 'p' : '-'
1065 static int pakfire_jail_set_capabilities(struct pakfire_jail
* jail
) {
1070 // Fetch capabilities
1071 caps
= cap_get_proc();
1073 ERROR(jail
->pakfire
, "Could not read capabilities: %m\n");
1078 // Walk through all capabilities
1079 for (cap_value_t cap
= 0; cap_valid(cap
); cap
++) {
1080 cap_value_t _caps
[] = { cap
};
1082 // Fetch the name of the capability
1083 name
= cap_to_name(cap
);
1085 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, _caps
, CAP_SET
);
1087 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1091 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, _caps
, CAP_SET
);
1093 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1097 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, _caps
, CAP_SET
);
1099 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1108 // Restore all capabilities
1109 r
= cap_set_proc(caps
);
1111 ERROR(jail
->pakfire
, "Restoring capabilities failed: %m\n");
1115 // Add all capabilities to the ambient set
1116 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1117 name
= cap_to_name(cap
);
1119 // Raise the capability
1120 r
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
1122 ERROR(jail
->pakfire
, "Could not set ambient capability %s: %m\n", name
);
1145 static int pakfire_jail_limit_syscalls(struct pakfire_jail
* jail
) {
1146 const int syscalls
[] = {
1147 // The kernel's keyring isn't namespaced
1150 SCMP_SYS(request_key
),
1152 // Disable userfaultfd
1153 SCMP_SYS(userfaultfd
),
1155 // Disable perf which could leak a lot of information about the host
1156 SCMP_SYS(perf_event_open
),
1162 DEBUG(jail
->pakfire
, "Applying syscall filter...\n");
1164 // Setup a syscall filter which allows everything by default
1165 scmp_filter_ctx ctx
= seccomp_init(SCMP_ACT_ALLOW
);
1167 ERROR(jail
->pakfire
, "Could not setup seccomp filter: %m\n");
1172 for (const int* syscall
= syscalls
; *syscall
; syscall
++) {
1173 r
= seccomp_rule_add(ctx
, SCMP_ACT_ERRNO(EPERM
), *syscall
, 0);
1175 ERROR(jail
->pakfire
, "Could not configure syscall %d: %m\n", *syscall
);
1180 // Load syscall filter into the kernel
1181 r
= seccomp_load(ctx
);
1183 ERROR(jail
->pakfire
, "Could not load syscall filter into the kernel: %m\n");
1189 seccomp_release(ctx
);
1196 PAKFIRE_EXPORT
int pakfire_jail_bind(struct pakfire_jail
* jail
,
1197 const char* source
, const char* target
, int flags
) {
1198 struct pakfire_jail_mountpoint
* mp
= NULL
;
1201 // Check if there is any space left
1202 if (jail
->num_mountpoints
>= MAX_MOUNTPOINTS
) {
1207 // Check for valid inputs
1208 if (!source
|| !target
) {
1213 // Select the next free slot
1214 mp
= &jail
->mountpoints
[jail
->num_mountpoints
];
1217 r
= pakfire_string_set(mp
->source
, source
);
1219 ERROR(jail
->pakfire
, "Could not copy source: %m\n");
1224 r
= pakfire_string_set(mp
->target
, target
);
1226 ERROR(jail
->pakfire
, "Could not copy target: %m\n");
1233 // Increment counter
1234 jail
->num_mountpoints
++;
1239 static int pakfire_jail_mount_networking(struct pakfire_jail
* jail
) {
1242 const char* paths
[] = {
1248 // Bind-mount all paths read-only
1249 for (const char** path
= paths
; *path
; path
++) {
1250 r
= pakfire_bind(jail
->pakfire
, *path
, NULL
, MS_RDONLY
);
1259 Mounts everything that we require in the new namespace
1261 static int pakfire_jail_mount(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1262 struct pakfire_jail_mountpoint
* mp
= NULL
;
1266 // Enable loop devices
1267 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_LOOP_DEVICES
))
1268 flags
|= PAKFIRE_MOUNT_LOOP_DEVICES
;
1270 // Mount all default stuff
1271 r
= pakfire_mount_all(jail
->pakfire
, flags
);
1275 // Mount networking stuff
1276 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1277 r
= pakfire_jail_mount_networking(jail
);
1282 // Mount all custom stuff
1283 for (unsigned int i
= 0; i
< jail
->num_mountpoints
; i
++) {
1285 mp
= &jail
->mountpoints
[i
];
1288 r
= pakfire_bind(jail
->pakfire
, mp
->source
, mp
->target
, mp
->flags
);
1293 // Log all mountpoints
1294 pakfire_mount_list(jail
->pakfire
);
1301 static int pakfire_jail_setup_loopback(struct pakfire_jail
* jail
) {
1302 struct nl_sock
* nl
= NULL
;
1303 struct nl_cache
* cache
= NULL
;
1304 struct rtnl_link
* link
= NULL
;
1305 struct rtnl_link
* change
= NULL
;
1308 DEBUG(jail
->pakfire
, "Setting up loopback...\n");
1310 // Allocate a netlink socket
1311 nl
= nl_socket_alloc();
1313 ERROR(jail
->pakfire
, "Could not allocate a netlink socket: %m\n");
1318 // Connect the socket
1319 r
= nl_connect(nl
, NETLINK_ROUTE
);
1321 ERROR(jail
->pakfire
, "Could not connect netlink socket: %s\n", nl_geterror(r
));
1325 // Allocate the netlink cache
1326 r
= rtnl_link_alloc_cache(nl
, AF_UNSPEC
, &cache
);
1328 ERROR(jail
->pakfire
, "Unable to allocate netlink cache: %s\n", nl_geterror(r
));
1332 // Fetch loopback interface
1333 link
= rtnl_link_get_by_name(cache
, "lo");
1335 ERROR(jail
->pakfire
, "Could not find lo interface. Ignoring.\n");
1340 // Allocate a new link
1341 change
= rtnl_link_alloc();
1343 ERROR(jail
->pakfire
, "Could not allocate change link\n");
1348 // Set the link to UP
1349 rtnl_link_set_flags(change
, IFF_UP
);
1351 // Apply any changes
1352 r
= rtnl_link_change(nl
, link
, change
, 0);
1354 ERROR(jail
->pakfire
, "Unable to activate loopback: %s\n", nl_geterror(r
));
1370 static int pakfire_jail_setup_uid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1371 char path
[PATH_MAX
];
1374 // Skip mapping anything when running on /
1375 if (pakfire_on_root(jail
->pakfire
))
1379 r
= pakfire_string_format(path
, "/proc/%d/uid_map", pid
);
1384 const uid_t uid
= pakfire_uid(jail
->pakfire
);
1387 const struct pakfire_subid
* subuid
= pakfire_subuid(jail
->pakfire
);
1391 /* When running as root, we will map the entire range.
1393 When running as a non-privileged user, we will map the root user inside the jail
1394 to the user's UID outside of the jail, and we will map the rest starting from one.
1399 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1400 "0 %lu %lu\n", subuid
->id
, subuid
->length
);
1402 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1403 "0 %lu 1\n1 %lu %lu\n", uid
, subuid
->id
, subuid
->length
);
1407 ERROR(jail
->pakfire
, "Could not map UIDs: %m\n");
1414 static int pakfire_jail_setup_gid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1415 char path
[PATH_MAX
];
1418 // Skip mapping anything when running on /
1419 if (pakfire_on_root(jail
->pakfire
))
1423 const gid_t gid
= pakfire_gid(jail
->pakfire
);
1426 const struct pakfire_subid
* subgid
= pakfire_subgid(jail
->pakfire
);
1431 r
= pakfire_string_format(path
, "/proc/%d/gid_map", pid
);
1437 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1438 "0 %lu %lu\n", subgid
->id
, subgid
->length
);
1440 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1441 "0 %lu 1\n%1 %lu %lu\n", gid
, subgid
->id
, subgid
->length
);
1445 ERROR(jail
->pakfire
, "Could not map GIDs: %m\n");
1452 static int pakfire_jail_setgroups(struct pakfire_jail
* jail
, pid_t pid
) {
1453 char path
[PATH_MAX
];
1457 r
= pakfire_string_format(path
, "/proc/%d/setgroups", pid
);
1461 // Open file for writing
1462 FILE* f
= fopen(path
, "w");
1464 ERROR(jail
->pakfire
, "Could not open %s for writing: %m\n", path
);
1469 int bytes_written
= fprintf(f
, "deny\n");
1470 if (bytes_written
<= 0) {
1471 ERROR(jail
->pakfire
, "Could not write to %s: %m\n", path
);
1478 ERROR(jail
->pakfire
, "Could not close %s: %m\n", path
);
1489 static int pakfire_jail_send_signal(struct pakfire_jail
* jail
, int fd
) {
1490 const uint64_t val
= 1;
1493 DEBUG(jail
->pakfire
, "Sending signal...\n");
1495 // Write to the file descriptor
1496 ssize_t bytes_written
= write(fd
, &val
, sizeof(val
));
1497 if (bytes_written
< 0 || (size_t)bytes_written
< sizeof(val
)) {
1498 ERROR(jail
->pakfire
, "Could not send signal: %m\n");
1502 // Close the file descriptor
1508 static int pakfire_jail_wait_for_signal(struct pakfire_jail
* jail
, int fd
) {
1512 DEBUG(jail
->pakfire
, "Waiting for signal...\n");
1514 ssize_t bytes_read
= read(fd
, &val
, sizeof(val
));
1515 if (bytes_read
< 0 || (size_t)bytes_read
< sizeof(val
)) {
1516 ERROR(jail
->pakfire
, "Error waiting for signal: %m\n");
1520 // Close the file descriptor
1527 Performs the initialisation that needs to happen in the parent part
1529 static int pakfire_jail_parent(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1532 // Setup UID mapping
1533 r
= pakfire_jail_setup_uid_mapping(jail
, ctx
->pid
);
1537 // Write "deny" to /proc/PID/setgroups
1538 r
= pakfire_jail_setgroups(jail
, ctx
->pid
);
1542 // Setup GID mapping
1543 r
= pakfire_jail_setup_gid_mapping(jail
, ctx
->pid
);
1547 // Parent has finished initialisation
1548 DEBUG(jail
->pakfire
, "Parent has finished initialization\n");
1550 // Send signal to client
1551 r
= pakfire_jail_send_signal(jail
, ctx
->completed_fd
);
1558 static int pakfire_jail_child(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
1559 const char* argv
[]) {
1562 // Redirect any logging to our log pipe
1563 pakfire_set_log_callback(jail
->pakfire
, pakfire_jail_log
, &ctx
->pipes
);
1566 r
= prctl(PR_SET_PDEATHSIG
, SIGKILL
, 0, 0, 0);
1568 ERROR(jail
->pakfire
, "Could not configure to die with parent: %m\n");
1573 pid_t pid
= getpid();
1575 DEBUG(jail
->pakfire
, "Launched child process in jail with PID %d\n", pid
);
1577 // Wait for the parent to finish initialization
1578 r
= pakfire_jail_wait_for_signal(jail
, ctx
->completed_fd
);
1582 // Perform further initialization
1585 uid_t uid
= getuid();
1586 gid_t gid
= getgid();
1589 uid_t euid
= geteuid();
1590 gid_t egid
= getegid();
1592 DEBUG(jail
->pakfire
, " UID: %d (effective %d)\n", uid
, euid
);
1593 DEBUG(jail
->pakfire
, " GID: %d (effective %d)\n", gid
, egid
);
1595 // Check if we are (effectively running as root)
1596 if (uid
|| gid
|| euid
|| egid
) {
1597 ERROR(jail
->pakfire
, "Child process is not running as root\n");
1601 const char* root
= pakfire_get_path(jail
->pakfire
);
1602 const char* arch
= pakfire_get_arch(jail
->pakfire
);
1604 // Change root (unless root is /)
1605 if (!pakfire_on_root(jail
->pakfire
)) {
1607 r
= pakfire_jail_mount(jail
, ctx
);
1614 ERROR(jail
->pakfire
, "chroot() to %s failed: %m\n", root
);
1618 // Change directory to /
1621 ERROR(jail
->pakfire
, "chdir() after chroot() failed: %m\n");
1627 unsigned long persona
= pakfire_arch_personality(arch
);
1629 r
= personality(persona
);
1631 ERROR(jail
->pakfire
, "Could not set personality (%x)\n", (unsigned int)persona
);
1637 if (!pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1638 r
= pakfire_jail_setup_loopback(jail
);
1645 DEBUG(jail
->pakfire
, "Setting nice level to %d\n", jail
->nice
);
1647 r
= setpriority(PRIO_PROCESS
, pid
, jail
->nice
);
1649 ERROR(jail
->pakfire
, "Could not set nice level: %m\n");
1654 // Close other end of log pipes
1655 close(ctx
->pipes
.log_INFO
[0]);
1656 close(ctx
->pipes
.log_ERROR
[0]);
1658 close(ctx
->pipes
.log_DEBUG
[0]);
1659 #endif /* ENABLE_DEBUG */
1661 // Connect standard input
1662 if (ctx
->pipes
.stdin
[0]) {
1663 r
= dup2(ctx
->pipes
.stdin
[0], STDIN_FILENO
);
1665 ERROR(jail
->pakfire
, "Could not connect fd %d to stdin: %m\n",
1666 ctx
->pipes
.stdin
[0]);
1672 // Connect standard output and error
1673 if (ctx
->pipes
.stdout
[1] && ctx
->pipes
.stderr
[1]) {
1674 r
= dup2(ctx
->pipes
.stdout
[1], STDOUT_FILENO
);
1676 ERROR(jail
->pakfire
, "Could not connect fd %d to stdout: %m\n",
1677 ctx
->pipes
.stdout
[1]);
1682 r
= dup2(ctx
->pipes
.stderr
[1], STDERR_FILENO
);
1684 ERROR(jail
->pakfire
, "Could not connect fd %d to stderr: %m\n",
1685 ctx
->pipes
.stderr
[1]);
1690 // Close the pipe (as we have moved the original file descriptors)
1691 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdin
);
1692 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdout
);
1693 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stderr
);
1696 // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
1697 r
= pakfire_rlimit_reset_nofile(jail
->pakfire
);
1701 // Don't drop any capabilities on execve()
1702 r
= prctl(PR_SET_KEEPCAPS
, 1);
1704 ERROR(jail
->pakfire
, "Could not set PR_SET_KEEPCAPS: %m\n");
1709 r
= pakfire_jail_set_capabilities(jail
);
1713 // Show capabilities
1714 r
= pakfire_jail_show_capabilities(jail
);
1719 r
= pakfire_jail_limit_syscalls(jail
);
1723 DEBUG(jail
->pakfire
, "Child process initialization done\n");
1724 DEBUG(jail
->pakfire
, "Launching command:\n");
1727 for (unsigned int i
= 0; argv
[i
]; i
++)
1728 DEBUG(jail
->pakfire
, " argv[%d] = %s\n", i
, argv
[i
]);
1731 r
= execvpe(argv
[0], (char**)argv
, jail
->env
);
1733 // Translate errno into regular exit code
1736 // Ignore if the command doesn't exist
1737 if (ctx
->flags
& PAKFIRE_JAIL_NOENT_OK
)
1748 ERROR(jail
->pakfire
, "Could not execve(%s): %m\n", argv
[0]);
1751 // We should not get here
1755 // Run a command in the jail
1756 static int __pakfire_jail_exec(struct pakfire_jail
* jail
, const char* argv
[],
1757 const int interactive
,
1758 pakfire_jail_communicate_in communicate_in
,
1759 pakfire_jail_communicate_out communicate_out
,
1760 void* data
, int flags
) {
1764 // Check if argv is valid
1765 if (!argv
|| !argv
[0]) {
1770 // Send any output to the default logger if no callback is set
1771 if (!communicate_out
)
1772 communicate_out
= pakfire_jail_default_log_callback
;
1774 // Initialize context for this call
1775 struct pakfire_jail_exec ctx
= {
1779 .stdin
= { -1, -1 },
1780 .stdout
= { -1, -1 },
1781 .stderr
= { -1, -1 },
1785 .in
= communicate_in
,
1786 .out
= communicate_out
,
1793 DEBUG(jail
->pakfire
, "Executing jail...\n");
1795 // Enable networking in interactive mode
1797 ctx
.flags
|= PAKFIRE_JAIL_HAS_NETWORKING
;
1800 Setup a file descriptor which can be used to notify the client that the parent
1801 has completed configuration.
1803 ctx
.completed_fd
= eventfd(0, EFD_CLOEXEC
);
1804 if (ctx
.completed_fd
< 0) {
1805 ERROR(jail
->pakfire
, "eventfd() failed: %m\n");
1809 // Create pipes to communicate with child process if we are not running interactively
1811 // stdin (only if callback is set)
1812 if (ctx
.communicate
.in
) {
1813 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdin
, 0);
1819 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdout
, 0);
1824 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stderr
, 0);
1829 // Setup pipes for logging
1831 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_INFO
, O_CLOEXEC
);
1836 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_ERROR
, O_CLOEXEC
);
1842 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_DEBUG
, O_CLOEXEC
);
1845 #endif /* ENABLE_DEBUG */
1847 // Configure child process
1848 struct clone_args args
= {
1857 .exit_signal
= SIGCHLD
,
1858 .pidfd
= (long long unsigned int)&ctx
.pidfd
,
1861 // Launch the process in a cgroup that is a leaf of the configured cgroup
1863 args
.flags
|= CLONE_INTO_CGROUP
;
1866 const char* uuid
= pakfire_jail_uuid(jail
);
1868 // Create a temporary cgroup
1869 r
= pakfire_cgroup_child(&ctx
.cgroup
, jail
->cgroup
, uuid
, 0);
1871 ERROR(jail
->pakfire
, "Could not create cgroup for jail: %m\n");
1875 // Clone into this cgroup
1876 args
.cgroup
= pakfire_cgroup_fd(ctx
.cgroup
);
1880 if (!pakfire_jail_exec_has_flag(&ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1881 args
.flags
|= CLONE_NEWNET
;
1884 // Fork this process
1885 ctx
.pid
= clone3(&args
, sizeof(args
));
1887 ERROR(jail
->pakfire
, "Could not clone: %m\n");
1891 } else if (ctx
.pid
== 0) {
1892 r
= pakfire_jail_child(jail
, &ctx
, argv
);
1897 r
= pakfire_jail_parent(jail
, &ctx
);
1901 DEBUG(jail
->pakfire
, "Waiting for PID %d to finish its work\n", ctx
.pid
);
1903 // Read output of the child process
1904 r
= pakfire_jail_wait(jail
, &ctx
);
1908 // Handle exit status
1909 switch (ctx
.status
.si_code
) {
1911 DEBUG(jail
->pakfire
, "The child process exited with code %d\n",
1912 ctx
.status
.si_status
);
1915 exit
= ctx
.status
.si_status
;
1919 ERROR(jail
->pakfire
, "The child process was killed\n");
1924 ERROR(jail
->pakfire
, "The child process terminated abnormally\n");
1927 // Log anything else
1929 ERROR(jail
->pakfire
, "Unknown child exit code: %d\n", ctx
.status
.si_code
);
1934 // Destroy the temporary cgroup (if any)
1936 // Read cgroup stats
1937 r
= pakfire_cgroup_stat(ctx
.cgroup
, &ctx
.cgroup_stats
);
1939 ERROR(jail
->pakfire
, "Could not read cgroup stats: %m\n");
1941 pakfire_cgroup_stat_dump(ctx
.cgroup
, &ctx
.cgroup_stats
);
1944 pakfire_cgroup_destroy(ctx
.cgroup
);
1945 pakfire_cgroup_unref(ctx
.cgroup
);
1948 // Close any file descriptors
1949 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdin
);
1950 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdout
);
1951 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stderr
);
1954 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_INFO
);
1955 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_ERROR
);
1956 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_DEBUG
);
1961 PAKFIRE_EXPORT
int pakfire_jail_exec(
1962 struct pakfire_jail
* jail
,
1964 pakfire_jail_communicate_in callback_in
,
1965 pakfire_jail_communicate_out callback_out
,
1966 void* data
, int flags
) {
1967 return __pakfire_jail_exec(jail
, argv
, 0, callback_in
, callback_out
, data
, flags
);
1970 static int pakfire_jail_exec_interactive(
1971 struct pakfire_jail
* jail
, const char* argv
[], int flags
) {
1974 // Setup interactive stuff
1975 r
= pakfire_jail_setup_interactive_env(jail
);
1979 return __pakfire_jail_exec(jail
, argv
, 1, NULL
, NULL
, NULL
, flags
);
1982 int pakfire_jail_exec_script(struct pakfire_jail
* jail
,
1986 pakfire_jail_communicate_in callback_in
,
1987 pakfire_jail_communicate_out callback_out
,
1989 char path
[PATH_MAX
];
1990 const char** argv
= NULL
;
1994 const char* root
= pakfire_get_path(jail
->pakfire
);
1996 // Write the scriptlet to disk
1997 r
= pakfire_path_join(path
, root
, PAKFIRE_TMP_DIR
"/pakfire-script.XXXXXX");
2001 // Create a temporary file
2002 f
= pakfire_mktemp(path
, 0700);
2004 ERROR(jail
->pakfire
, "Could not create temporary file: %m\n");
2008 DEBUG(jail
->pakfire
, "Writing script to %s:\n%.*s\n", path
, (int)size
, script
);
2011 r
= fprintf(f
, "%s", script
);
2013 ERROR(jail
->pakfire
, "Could not write script to file %s: %m\n", path
);
2020 ERROR(jail
->pakfire
, "Could not close script file %s: %m\n", path
);
2026 // Count how many arguments were passed
2027 unsigned int argc
= 1;
2029 for (const char** arg
= args
; *arg
; arg
++)
2033 argv
= calloc(argc
+ 1, sizeof(*argv
));
2035 ERROR(jail
->pakfire
, "Could not allocate argv: %m\n");
2040 argv
[0] = (root
) ? pakfire_path_relpath(root
, path
) : path
;
2043 for (unsigned int i
= 1; i
< argc
; i
++)
2044 argv
[i
] = args
[i
-1];
2047 r
= pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, 0);
2055 // Remove script from disk
2063 A convenience function that creates a new jail, runs the given command and destroys
2066 int pakfire_jail_run(struct pakfire
* pakfire
, const char* argv
[], int flags
, char** output
) {
2067 struct pakfire_jail
* jail
= NULL
;
2070 // Create a new jail
2071 r
= pakfire_jail_create(&jail
, pakfire
);
2075 // Execute the command
2076 r
= pakfire_jail_exec(jail
, argv
, NULL
, pakfire_jail_capture_stdout
, output
, 0);
2080 pakfire_jail_unref(jail
);
2085 int pakfire_jail_run_script(struct pakfire
* pakfire
,
2086 const char* script
, const size_t length
, const char* argv
[], int flags
) {
2087 struct pakfire_jail
* jail
= NULL
;
2090 // Create a new jail
2091 r
= pakfire_jail_create(&jail
, pakfire
);
2095 // Execute the command
2096 r
= pakfire_jail_exec_script(jail
, script
, length
, argv
, NULL
, NULL
, NULL
);
2100 pakfire_jail_unref(jail
);
2105 int pakfire_jail_shell(struct pakfire_jail
* jail
) {
2106 const char* argv
[] = {
2107 "/bin/bash", "--login", NULL
,
2110 // Execute /bin/bash
2111 return pakfire_jail_exec_interactive(jail
, argv
, 0);
2114 static int pakfire_jail_run_if_possible(struct pakfire
* pakfire
, const char** argv
) {
2115 char path
[PATH_MAX
];
2118 r
= pakfire_path(pakfire
, path
, "%s", *argv
);
2122 // Check if the file is executable
2123 r
= access(path
, X_OK
);
2125 DEBUG(pakfire
, "%s is not executable. Skipping...\n", *argv
);
2129 return pakfire_jail_run(pakfire
, argv
, 0, NULL
);
2132 int pakfire_jail_ldconfig(struct pakfire
* pakfire
) {
2133 const char* argv
[] = {
2138 return pakfire_jail_run_if_possible(pakfire
, argv
);
2141 int pakfire_jail_run_systemd_tmpfiles(struct pakfire
* pakfire
) {
2142 const char* argv
[] = {
2143 "/usr/bin/systemd-tmpfiles",
2148 return pakfire_jail_run_if_possible(pakfire
, argv
);