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 pivot_root(const char* new_root
, const char* old_root
) {
176 return syscall(SYS_pivot_root
, new_root
, old_root
);
179 static int pakfire_jail_exec_has_flag(
180 const struct pakfire_jail_exec
* ctx
, const enum pakfire_jail_exec_flags flag
) {
181 return ctx
->flags
& flag
;
184 static void pakfire_jail_free(struct pakfire_jail
* jail
) {
185 DEBUG(jail
->pakfire
, "Freeing jail at %p\n", jail
);
188 for (unsigned int i
= 0; jail
->env
[i
]; i
++)
192 pakfire_cgroup_unref(jail
->cgroup
);
194 pakfire_unref(jail
->pakfire
);
199 Passes any log messages on to the default pakfire log callback
201 static int pakfire_jail_default_log_callback(struct pakfire
* pakfire
, void* data
,
202 int priority
, const char* line
, size_t length
) {
205 INFO(pakfire
, "%s", line
);
209 ERROR(pakfire
, "%s", line
);
214 DEBUG(pakfire
, "%s", line
);
222 static const char* pakfire_jail_uuid(struct pakfire_jail
* jail
) {
224 uuid_unparse_lower(jail
->uuid
, jail
->__uuid
);
229 static int pakfire_jail_setup_interactive_env(struct pakfire_jail
* jail
) {
231 int r
= pakfire_jail_set_env(jail
, "PS1", "pakfire-jail \\w> ");
236 char* TERM
= secure_getenv("TERM");
238 r
= pakfire_jail_set_env(jail
, "TERM", TERM
);
244 char* LANG
= secure_getenv("LANG");
246 r
= pakfire_jail_set_env(jail
, "LANG", LANG
);
254 PAKFIRE_EXPORT
int pakfire_jail_create(struct pakfire_jail
** jail
, struct pakfire
* pakfire
) {
257 const char* arch
= pakfire_get_effective_arch(pakfire
);
259 // Allocate a new jail
260 struct pakfire_jail
* j
= calloc(1, sizeof(*j
));
265 j
->pakfire
= pakfire_ref(pakfire
);
267 // Initialize reference counter
270 // Generate a random UUID
271 uuid_generate_random(j
->uuid
);
273 DEBUG(j
->pakfire
, "Allocated new jail at %p\n", j
);
275 // Set default environment
276 for (const struct environ
* e
= ENV
; e
->key
; e
++) {
277 r
= pakfire_jail_set_env(j
, e
->key
, e
->val
);
282 // Enable all CPU features that CPU has to offer
283 if (!pakfire_arch_is_supported_by_host(arch
)) {
284 r
= pakfire_jail_set_env(j
, "QEMU_CPU", "max");
289 // Set container UUID
290 r
= pakfire_jail_set_env(j
, "container_uuid", pakfire_jail_uuid(j
));
294 // Disable systemctl to talk to systemd
295 if (!pakfire_on_root(j
->pakfire
)) {
296 r
= pakfire_jail_set_env(j
, "SYSTEMD_OFFLINE", "1");
306 pakfire_jail_free(j
);
311 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_ref(struct pakfire_jail
* jail
) {
317 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_unref(struct pakfire_jail
* jail
) {
318 if (--jail
->nrefs
> 0)
321 pakfire_jail_free(jail
);
327 PAKFIRE_EXPORT
int pakfire_jail_nice(struct pakfire_jail
* jail
, int nice
) {
328 // Check if nice level is in range
329 if (nice
< -19 || nice
> 20) {
340 int pakfire_jail_set_cgroup(struct pakfire_jail
* jail
, struct pakfire_cgroup
* cgroup
) {
341 // Free any previous cgroup
343 pakfire_cgroup_unref(jail
->cgroup
);
347 // Set any new cgroup
349 DEBUG(jail
->pakfire
, "Setting cgroup %p\n", cgroup
);
351 jail
->cgroup
= pakfire_cgroup_ref(cgroup
);
360 // Returns the length of the environment
361 static unsigned int pakfire_jail_env_length(struct pakfire_jail
* jail
) {
364 // Count everything in the environment
365 for (char** e
= jail
->env
; *e
; e
++)
371 // Finds an existing environment variable and returns its index or -1 if not found
372 static int pakfire_jail_find_env(struct pakfire_jail
* jail
, const char* key
) {
378 const size_t length
= strlen(key
);
380 for (unsigned int i
= 0; jail
->env
[i
]; i
++) {
381 if ((pakfire_string_startswith(jail
->env
[i
], key
)
382 && *(jail
->env
[i
] + length
) == '=')) {
391 // Returns the value of an environment variable or NULL
392 PAKFIRE_EXPORT
const char* pakfire_jail_get_env(struct pakfire_jail
* jail
,
394 int i
= pakfire_jail_find_env(jail
, key
);
398 return jail
->env
[i
] + strlen(key
) + 1;
401 // Sets an environment variable
402 PAKFIRE_EXPORT
int pakfire_jail_set_env(struct pakfire_jail
* jail
,
403 const char* key
, const char* value
) {
404 // Find the index where to write this value to
405 int i
= pakfire_jail_find_env(jail
, key
);
407 i
= pakfire_jail_env_length(jail
);
409 // Return -ENOSPC when the environment is full
410 if (i
>= ENVIRON_SIZE
) {
415 // Free any previous value
419 // Format and set environment variable
420 asprintf(&jail
->env
[i
], "%s=%s", key
, value
);
422 DEBUG(jail
->pakfire
, "Set environment variable: %s\n", jail
->env
[i
]);
427 // Imports an environment
428 PAKFIRE_EXPORT
int pakfire_jail_import_env(struct pakfire_jail
* jail
, const char* env
[]) {
436 // Copy environment variables
437 for (unsigned int i
= 0; env
[i
]; i
++) {
438 r
= pakfire_string_partition(env
[i
], "=", &key
, &val
);
443 r
= pakfire_jail_set_env(jail
, key
, val
);
460 PAKFIRE_EXPORT
int pakfire_jail_set_timeout(
461 struct pakfire_jail
* jail
, unsigned int timeout
) {
463 jail
->timeout
.it_value
.tv_sec
= timeout
;
466 DEBUG(jail
->pakfire
, "Timeout set to %d second(s)\n", timeout
);
468 DEBUG(jail
->pakfire
, "Timeout disabled\n");
473 static int pakfire_jail_create_timer(struct pakfire_jail
* jail
) {
476 // Nothing to do if no timeout has been set
477 if (!jail
->timeout
.it_value
.tv_sec
)
480 // Create a new timer
481 const int fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
483 ERROR(jail
->pakfire
, "Could not create timer: %m\n");
488 r
= timerfd_settime(fd
, 0, &jail
->timeout
, NULL
);
490 ERROR(jail
->pakfire
, "Could not arm timer: %m\n");
505 static int pakfire_jail_handle_signals(struct pakfire_jail
* jail
) {
510 sigaddset(&mask
, SIGINT
);
513 r
= sigprocmask(SIG_BLOCK
, &mask
, NULL
);
515 ERROR(jail
->pakfire
, "Failed to block signals: %m\n");
519 // Create a file descriptor
520 r
= signalfd(-1, &mask
, SFD_NONBLOCK
|SFD_CLOEXEC
);
522 ERROR(jail
->pakfire
, "Failed to create signalfd: %m\n");
530 This function replaces any logging in the child process.
532 All log messages will be sent to the parent process through their respective pipes.
534 static void pakfire_jail_log(void* data
, int priority
, const char* file
,
535 int line
, const char* fn
, const char* format
, va_list args
) {
536 struct pakfire_jail_pipes
* pipes
= (struct pakfire_jail_pipes
*)data
;
541 fd
= pipes
->log_INFO
[1];
545 fd
= pipes
->log_ERROR
[1];
550 fd
= pipes
->log_DEBUG
[1];
552 #endif /* ENABLE_DEBUG */
554 // Ignore any messages of an unknown priority
559 // Send the log message
561 vdprintf(fd
, format
, args
);
564 static int pakfire_jail_log_buffer_is_full(const struct pakfire_log_buffer
* buffer
) {
565 return (sizeof(buffer
->data
) == buffer
->used
);
569 This function reads as much data as it can from the file descriptor.
570 If it finds a whole line in it, it will send it to the logger and repeat the process.
571 If not newline character is found, it will try to read more data until it finds one.
573 static int pakfire_jail_handle_log(struct pakfire_jail
* jail
,
574 struct pakfire_jail_exec
* ctx
, int priority
, int fd
,
575 struct pakfire_log_buffer
* buffer
, pakfire_jail_communicate_out callback
, void* data
) {
576 char line
[BUFFER_SIZE
+ 1];
578 // Fill up buffer from fd
579 if (buffer
->used
< sizeof(buffer
->data
)) {
580 ssize_t bytes_read
= read(fd
, buffer
->data
+ buffer
->used
,
581 sizeof(buffer
->data
) - buffer
->used
);
584 if (bytes_read
< 0) {
585 ERROR(jail
->pakfire
, "Could not read from fd %d: %m\n", fd
);
589 // Update buffer size
590 buffer
->used
+= bytes_read
;
593 // See if we have any lines that we can write
594 while (buffer
->used
) {
595 // Search for the end of the first line
596 char* eol
= memchr(buffer
->data
, '\n', buffer
->used
);
600 // If the buffer is full, we send the content to the logger and try again
601 // This should not happen in practise
602 if (pakfire_jail_log_buffer_is_full(buffer
)) {
603 DEBUG(jail
->pakfire
, "Logging buffer is full. Sending all content\n");
605 eol
= buffer
->data
+ sizeof(buffer
->data
) - 1;
607 // Otherwise we might have only read parts of the output
612 // Find the length of the string
613 size_t length
= eol
- buffer
->data
+ 1;
615 // Copy the line into the buffer
616 memcpy(line
, buffer
->data
, length
);
618 // Terminate the string
623 int r
= callback(jail
->pakfire
, data
, priority
, line
, length
);
625 ERROR(jail
->pakfire
, "The logging callback returned an error: %d\n", r
);
630 // Remove line from buffer
631 memmove(buffer
->data
, buffer
->data
+ length
, buffer
->used
- length
);
632 buffer
->used
-= length
;
638 static int pakfire_jail_stream_stdin(struct pakfire_jail
* jail
,
639 struct pakfire_jail_exec
* ctx
, const int fd
) {
642 // Nothing to do if there is no stdin callback set
643 if (!ctx
->communicate
.in
) {
644 DEBUG(jail
->pakfire
, "Callback for standard input is not set\n");
648 // Skip if the writing pipe has already been closed
649 if (!ctx
->pipes
.stdin
[1])
652 DEBUG(jail
->pakfire
, "Streaming standard input...\n");
654 // Calling the callback
655 r
= ctx
->communicate
.in(jail
->pakfire
, ctx
->communicate
.data
, fd
);
657 DEBUG(jail
->pakfire
, "Standard input callback finished: %d\n", r
);
659 // The callback signaled that it has written everything
661 DEBUG(jail
->pakfire
, "Closing standard input pipe\n");
663 // Close the file-descriptor
666 // Reset the file-descriptor so it won't be closed again later
667 ctx
->pipes
.stdin
[1] = 0;
676 static int pakfire_jail_setup_pipe(struct pakfire_jail
* jail
, int (*fds
)[2], const int flags
) {
677 int r
= pipe2(*fds
, flags
);
679 ERROR(jail
->pakfire
, "Could not setup pipe: %m\n");
686 static void pakfire_jail_close_pipe(struct pakfire_jail
* jail
, int fds
[2]) {
687 for (unsigned int i
= 0; i
< 2; i
++)
693 This is a convenience function to fetch the reading end of a pipe and
694 closes the write end.
696 static int pakfire_jail_get_pipe_to_read(struct pakfire_jail
* jail
, int (*fds
)[2]) {
697 // Give the variables easier names to avoid confusion
698 int* fd_read
= &(*fds
)[0];
699 int* fd_write
= &(*fds
)[1];
701 // Close the write end of the pipe
707 // Return the read end
711 static int pakfire_jail_get_pipe_to_write(struct pakfire_jail
* jail
, int (*fds
)[2]) {
712 // Give the variables easier names to avoid confusion
713 int* fd_read
= &(*fds
)[0];
714 int* fd_write
= &(*fds
)[1];
716 // Close the read end of the pipe
722 // Return the write end
726 static int pakfire_jail_wait(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
728 struct epoll_event ev
;
729 struct epoll_event events
[EPOLL_MAX_EVENTS
];
730 struct signalfd_siginfo siginfo
;
734 // Fetch file descriptors from context
735 const int stdin
= pakfire_jail_get_pipe_to_write(jail
, &ctx
->pipes
.stdin
);
736 const int stdout
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stdout
);
737 const int stderr
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.stderr
);
738 const int pidfd
= ctx
->pidfd
;
741 const int timerfd
= pakfire_jail_create_timer(jail
);
744 const int log_INFO
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_INFO
);
745 const int log_ERROR
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_ERROR
);
746 const int log_DEBUG
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_DEBUG
);
749 const int signalfd
= pakfire_jail_handle_signals(jail
);
751 // Make a list of all file descriptors we are interested in
753 stdin
, stdout
, stderr
, pidfd
, timerfd
, signalfd
, log_INFO
, log_ERROR
, log_DEBUG
,
757 epollfd
= epoll_create1(0);
759 ERROR(jail
->pakfire
, "Could not initialize epoll(): %m\n");
764 // Turn file descriptors into non-blocking mode and add them to epoll()
765 for (unsigned int i
= 0; i
< sizeof(fds
) / sizeof(*fds
); i
++) {
768 // Skip fds which were not initialized
772 ev
.events
= EPOLLHUP
;
775 ev
.events
|= EPOLLOUT
;
777 ev
.events
|= EPOLLIN
;
780 int flags
= fcntl(fd
, F_GETFL
, 0);
782 // Set modified flags
783 if (fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
) < 0) {
785 "Could not set file descriptor %d into non-blocking mode: %m\n", fd
);
792 if (epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fd
, &ev
) < 0) {
793 ERROR(jail
->pakfire
, "Could not add file descriptor %d to epoll(): %m\n", fd
);
801 // Loop for as long as the process is alive
803 int num
= epoll_wait(epollfd
, events
, EPOLL_MAX_EVENTS
, -1);
805 // Ignore if epoll_wait() has been interrupted
809 ERROR(jail
->pakfire
, "epoll_wait() failed: %m\n");
815 for (int i
= 0; i
< num
; i
++) {
816 int e
= events
[i
].events
;
817 int fd
= events
[i
].data
.fd
;
819 struct pakfire_log_buffer
* buffer
= NULL
;
820 pakfire_jail_communicate_out callback
= NULL
;
824 // Check if there is any data to be read
826 // Handle any changes to the PIDFD
828 // Call waidid() and store the result
829 r
= waitid(P_PIDFD
, ctx
->pidfd
, &ctx
->status
, WEXITED
);
831 ERROR(jail
->pakfire
, "waitid() failed: %m\n");
835 // Mark that we have ended so that we will process the remaining
836 // events from epoll() now, but won't restart the outer loop.
840 // Handle timer events
841 } else if (fd
== timerfd
) {
842 DEBUG(jail
->pakfire
, "Timer event received\n");
845 r
= read(timerfd
, garbage
, sizeof(garbage
));
847 ERROR(jail
->pakfire
, "Could not disarm timer: %m\n");
852 // Terminate the process if it hasn't already ended
854 DEBUG(jail
->pakfire
, "Terminating process...\n");
856 // Send SIGTERM to the process
857 r
= pidfd_send_signal(pidfd
, SIGKILL
, NULL
, 0);
859 ERROR(jail
->pakfire
, "Could not kill process: %m\n");
864 // There is nothing else to do
868 } else if (fd
== signalfd
) {
870 r
= read(signalfd
, &siginfo
, sizeof(siginfo
));
872 ERROR(jail
->pakfire
, "Could not read signal: %m\n");
876 DEBUG(jail
->pakfire
, "Received signal %d\n", siginfo
.ssi_signo
);
879 switch (siginfo
.ssi_signo
) {
880 // Pass SIGINT down to the child process
882 r
= pidfd_send_signal(pidfd
, siginfo
.ssi_signo
, NULL
, 0);
884 ERROR(jail
->pakfire
, "Could not send signal to process: %m\n");
890 ERROR(jail
->pakfire
, "Received unhandled signal %d\n",
895 // Don't fall through to log processing
898 // Handle logging messages
899 } else if (fd
== log_INFO
) {
900 buffer
= &ctx
->buffers
.log_INFO
;
903 callback
= pakfire_jail_default_log_callback
;
905 } else if (fd
== log_ERROR
) {
906 buffer
= &ctx
->buffers
.log_ERROR
;
909 callback
= pakfire_jail_default_log_callback
;
911 } else if (fd
== log_DEBUG
) {
912 buffer
= &ctx
->buffers
.log_DEBUG
;
913 priority
= LOG_DEBUG
;
915 callback
= pakfire_jail_default_log_callback
;
917 // Handle anything from the log pipes
918 } else if (fd
== stdout
) {
919 buffer
= &ctx
->buffers
.stdout
;
922 callback
= ctx
->communicate
.out
;
923 data
= ctx
->communicate
.data
;
925 } else if (fd
== stderr
) {
926 buffer
= &ctx
->buffers
.stderr
;
929 callback
= ctx
->communicate
.out
;
930 data
= ctx
->communicate
.data
;
933 DEBUG(jail
->pakfire
, "Received invalid file descriptor %d\n", fd
);
938 r
= pakfire_jail_handle_log(jail
, ctx
, priority
, fd
, buffer
, callback
, data
);
944 // Handle standard input
946 r
= pakfire_jail_stream_stdin(jail
, ctx
, fd
);
949 // Ignore if we filled up the buffer
954 ERROR(jail
->pakfire
, "Could not write to stdin: %m\n");
961 // Check if any file descriptors have been closed
963 // Remove the file descriptor
964 r
= epoll_ctl(epollfd
, EPOLL_CTL_DEL
, fd
, NULL
);
966 ERROR(jail
->pakfire
, "Could not remove closed file-descriptor %d: %m\n", fd
);
984 int pakfire_jail_capture_stdout(struct pakfire
* pakfire
, void* data
,
985 int priority
, const char* line
, size_t length
) {
986 char** output
= (char**)data
;
989 // Append everything from stdout to a buffer
990 if (output
&& priority
== LOG_INFO
) {
991 r
= asprintf(output
, "%s%s", (output
&& *output
) ? *output
: "", line
);
997 // Send everything else to the default logger
998 return pakfire_jail_default_log_callback(pakfire
, NULL
, priority
, line
, length
);
1003 // Logs all capabilities of the current process
1004 static int pakfire_jail_show_capabilities(struct pakfire_jail
* jail
) {
1007 cap_flag_value_t value_e
;
1008 cap_flag_value_t value_i
;
1009 cap_flag_value_t value_p
;
1013 pid_t pid
= getpid();
1015 // Fetch all capabilities
1016 caps
= cap_get_proc();
1018 ERROR(jail
->pakfire
, "Could not fetch capabilities: %m\n");
1023 DEBUG(jail
->pakfire
, "Capabilities of PID %d:\n", pid
);
1025 // Iterate over all capabilities
1026 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1027 name
= cap_to_name(cap
);
1029 // Fetch effective value
1030 r
= cap_get_flag(caps
, cap
, CAP_EFFECTIVE
, &value_e
);
1034 // Fetch inheritable value
1035 r
= cap_get_flag(caps
, cap
, CAP_INHERITABLE
, &value_i
);
1039 // Fetch permitted value
1040 r
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &value_p
);
1044 DEBUG(jail
->pakfire
,
1045 " %-24s : %c%c%c\n",
1047 (value_e
== CAP_SET
) ? 'e' : '-',
1048 (value_i
== CAP_SET
) ? 'i' : '-',
1049 (value_p
== CAP_SET
) ? 'p' : '-'
1069 static int pakfire_jail_set_capabilities(struct pakfire_jail
* jail
) {
1074 // Fetch capabilities
1075 caps
= cap_get_proc();
1077 ERROR(jail
->pakfire
, "Could not read capabilities: %m\n");
1082 // Walk through all capabilities
1083 for (cap_value_t cap
= 0; cap_valid(cap
); cap
++) {
1084 cap_value_t _caps
[] = { cap
};
1086 // Fetch the name of the capability
1087 name
= cap_to_name(cap
);
1089 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, _caps
, CAP_SET
);
1091 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1095 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, _caps
, CAP_SET
);
1097 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1101 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, _caps
, CAP_SET
);
1103 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1112 // Restore all capabilities
1113 r
= cap_set_proc(caps
);
1115 ERROR(jail
->pakfire
, "Restoring capabilities failed: %m\n");
1119 // Add all capabilities to the ambient set
1120 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1121 name
= cap_to_name(cap
);
1123 // Raise the capability
1124 r
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
1126 ERROR(jail
->pakfire
, "Could not set ambient capability %s: %m\n", name
);
1149 static int pakfire_jail_limit_syscalls(struct pakfire_jail
* jail
) {
1150 const int syscalls
[] = {
1151 // The kernel's keyring isn't namespaced
1154 SCMP_SYS(request_key
),
1156 // Disable userfaultfd
1157 SCMP_SYS(userfaultfd
),
1159 // Disable perf which could leak a lot of information about the host
1160 SCMP_SYS(perf_event_open
),
1166 DEBUG(jail
->pakfire
, "Applying syscall filter...\n");
1168 // Setup a syscall filter which allows everything by default
1169 scmp_filter_ctx ctx
= seccomp_init(SCMP_ACT_ALLOW
);
1171 ERROR(jail
->pakfire
, "Could not setup seccomp filter: %m\n");
1176 for (const int* syscall
= syscalls
; *syscall
; syscall
++) {
1177 r
= seccomp_rule_add(ctx
, SCMP_ACT_ERRNO(EPERM
), *syscall
, 0);
1179 ERROR(jail
->pakfire
, "Could not configure syscall %d: %m\n", *syscall
);
1184 // Load syscall filter into the kernel
1185 r
= seccomp_load(ctx
);
1187 ERROR(jail
->pakfire
, "Could not load syscall filter into the kernel: %m\n");
1193 seccomp_release(ctx
);
1200 PAKFIRE_EXPORT
int pakfire_jail_bind(struct pakfire_jail
* jail
,
1201 const char* source
, const char* target
, int flags
) {
1202 struct pakfire_jail_mountpoint
* mp
= NULL
;
1205 // Check if there is any space left
1206 if (jail
->num_mountpoints
>= MAX_MOUNTPOINTS
) {
1211 // Check for valid inputs
1212 if (!source
|| !target
) {
1217 // Select the next free slot
1218 mp
= &jail
->mountpoints
[jail
->num_mountpoints
];
1221 r
= pakfire_string_set(mp
->source
, source
);
1223 ERROR(jail
->pakfire
, "Could not copy source: %m\n");
1228 r
= pakfire_string_set(mp
->target
, target
);
1230 ERROR(jail
->pakfire
, "Could not copy target: %m\n");
1237 // Increment counter
1238 jail
->num_mountpoints
++;
1243 static int pakfire_jail_mount_networking(struct pakfire_jail
* jail
) {
1246 const char* paths
[] = {
1252 // Bind-mount all paths read-only
1253 for (const char** path
= paths
; *path
; path
++) {
1254 r
= pakfire_bind(jail
->pakfire
, *path
, NULL
, MS_RDONLY
);
1263 Mounts everything that we require in the new namespace
1265 static int pakfire_jail_mount(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1266 struct pakfire_jail_mountpoint
* mp
= NULL
;
1270 // Enable loop devices
1271 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_LOOP_DEVICES
))
1272 flags
|= PAKFIRE_MOUNT_LOOP_DEVICES
;
1274 // Mount all default stuff
1275 r
= pakfire_mount_all(jail
->pakfire
, flags
);
1279 // Mount networking stuff
1280 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1281 r
= pakfire_jail_mount_networking(jail
);
1286 // Mount all custom stuff
1287 for (unsigned int i
= 0; i
< jail
->num_mountpoints
; i
++) {
1289 mp
= &jail
->mountpoints
[i
];
1292 r
= pakfire_bind(jail
->pakfire
, mp
->source
, mp
->target
, mp
->flags
);
1297 // Log all mountpoints
1298 pakfire_mount_list(jail
->pakfire
);
1305 static int pakfire_jail_setup_loopback(struct pakfire_jail
* jail
) {
1306 struct nl_sock
* nl
= NULL
;
1307 struct nl_cache
* cache
= NULL
;
1308 struct rtnl_link
* link
= NULL
;
1309 struct rtnl_link
* change
= NULL
;
1312 DEBUG(jail
->pakfire
, "Setting up loopback...\n");
1314 // Allocate a netlink socket
1315 nl
= nl_socket_alloc();
1317 ERROR(jail
->pakfire
, "Could not allocate a netlink socket: %m\n");
1322 // Connect the socket
1323 r
= nl_connect(nl
, NETLINK_ROUTE
);
1325 ERROR(jail
->pakfire
, "Could not connect netlink socket: %s\n", nl_geterror(r
));
1329 // Allocate the netlink cache
1330 r
= rtnl_link_alloc_cache(nl
, AF_UNSPEC
, &cache
);
1332 ERROR(jail
->pakfire
, "Unable to allocate netlink cache: %s\n", nl_geterror(r
));
1336 // Fetch loopback interface
1337 link
= rtnl_link_get_by_name(cache
, "lo");
1339 ERROR(jail
->pakfire
, "Could not find lo interface. Ignoring.\n");
1344 // Allocate a new link
1345 change
= rtnl_link_alloc();
1347 ERROR(jail
->pakfire
, "Could not allocate change link\n");
1352 // Set the link to UP
1353 rtnl_link_set_flags(change
, IFF_UP
);
1355 // Apply any changes
1356 r
= rtnl_link_change(nl
, link
, change
, 0);
1358 ERROR(jail
->pakfire
, "Unable to activate loopback: %s\n", nl_geterror(r
));
1374 static int pakfire_jail_setup_uid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1375 char path
[PATH_MAX
];
1378 // Skip mapping anything when running on /
1379 if (pakfire_on_root(jail
->pakfire
))
1383 r
= pakfire_string_format(path
, "/proc/%d/uid_map", pid
);
1388 const uid_t uid
= pakfire_uid(jail
->pakfire
);
1391 const struct pakfire_subid
* subuid
= pakfire_subuid(jail
->pakfire
);
1395 /* When running as root, we will map the entire range.
1397 When running as a non-privileged user, we will map the root user inside the jail
1398 to the user's UID outside of the jail, and we will map the rest starting from one.
1403 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1404 "0 %lu %lu\n", subuid
->id
, subuid
->length
);
1406 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1407 "0 %lu 1\n1 %lu %lu\n", uid
, subuid
->id
, subuid
->length
);
1411 ERROR(jail
->pakfire
, "Could not map UIDs: %m\n");
1418 static int pakfire_jail_setup_gid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1419 char path
[PATH_MAX
];
1422 // Skip mapping anything when running on /
1423 if (pakfire_on_root(jail
->pakfire
))
1427 const gid_t gid
= pakfire_gid(jail
->pakfire
);
1430 const struct pakfire_subid
* subgid
= pakfire_subgid(jail
->pakfire
);
1435 r
= pakfire_string_format(path
, "/proc/%d/gid_map", pid
);
1441 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1442 "0 %lu %lu\n", subgid
->id
, subgid
->length
);
1444 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1445 "0 %lu 1\n%1 %lu %lu\n", gid
, subgid
->id
, subgid
->length
);
1449 ERROR(jail
->pakfire
, "Could not map GIDs: %m\n");
1456 static int pakfire_jail_setgroups(struct pakfire_jail
* jail
, pid_t pid
) {
1457 char path
[PATH_MAX
];
1461 r
= pakfire_string_format(path
, "/proc/%d/setgroups", pid
);
1465 // Open file for writing
1466 FILE* f
= fopen(path
, "w");
1468 ERROR(jail
->pakfire
, "Could not open %s for writing: %m\n", path
);
1473 int bytes_written
= fprintf(f
, "deny\n");
1474 if (bytes_written
<= 0) {
1475 ERROR(jail
->pakfire
, "Could not write to %s: %m\n", path
);
1482 ERROR(jail
->pakfire
, "Could not close %s: %m\n", path
);
1493 static int pakfire_jail_send_signal(struct pakfire_jail
* jail
, int fd
) {
1494 const uint64_t val
= 1;
1497 DEBUG(jail
->pakfire
, "Sending signal...\n");
1499 // Write to the file descriptor
1500 ssize_t bytes_written
= write(fd
, &val
, sizeof(val
));
1501 if (bytes_written
< 0 || (size_t)bytes_written
< sizeof(val
)) {
1502 ERROR(jail
->pakfire
, "Could not send signal: %m\n");
1506 // Close the file descriptor
1512 static int pakfire_jail_wait_for_signal(struct pakfire_jail
* jail
, int fd
) {
1516 DEBUG(jail
->pakfire
, "Waiting for signal...\n");
1518 ssize_t bytes_read
= read(fd
, &val
, sizeof(val
));
1519 if (bytes_read
< 0 || (size_t)bytes_read
< sizeof(val
)) {
1520 ERROR(jail
->pakfire
, "Error waiting for signal: %m\n");
1524 // Close the file descriptor
1531 Performs the initialisation that needs to happen in the parent part
1533 static int pakfire_jail_parent(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1536 // Setup UID mapping
1537 r
= pakfire_jail_setup_uid_mapping(jail
, ctx
->pid
);
1541 // Write "deny" to /proc/PID/setgroups
1542 r
= pakfire_jail_setgroups(jail
, ctx
->pid
);
1546 // Setup GID mapping
1547 r
= pakfire_jail_setup_gid_mapping(jail
, ctx
->pid
);
1551 // Parent has finished initialisation
1552 DEBUG(jail
->pakfire
, "Parent has finished initialization\n");
1554 // Send signal to client
1555 r
= pakfire_jail_send_signal(jail
, ctx
->completed_fd
);
1562 static int pakfire_jail_switch_root(struct pakfire_jail
* jail
, const char* root
) {
1565 // Change to the new root
1568 ERROR(jail
->pakfire
, "chdir(%s) failed: %m\n", root
);
1573 r
= pivot_root(".", ".");
1575 ERROR(jail
->pakfire
, "Failed changing into the new root directory %s: %m\n", root
);
1579 // Umount the old root
1580 r
= umount2(".", MNT_DETACH
);
1582 ERROR(jail
->pakfire
, "Could not umount the old root filesystem: %m\n");
1589 static int pakfire_jail_child(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
1590 const char* argv
[]) {
1593 // Redirect any logging to our log pipe
1594 pakfire_set_log_callback(jail
->pakfire
, pakfire_jail_log
, &ctx
->pipes
);
1597 pid_t pid
= getpid();
1599 DEBUG(jail
->pakfire
, "Launched child process in jail with PID %d\n", pid
);
1601 // Wait for the parent to finish initialization
1602 r
= pakfire_jail_wait_for_signal(jail
, ctx
->completed_fd
);
1607 r
= prctl(PR_SET_PDEATHSIG
, SIGKILL
, 0, 0, 0);
1609 ERROR(jail
->pakfire
, "Could not configure to die with parent: %m\n");
1613 // Make this process dumpable
1614 r
= prctl (PR_SET_DUMPABLE
, 1, 0, 0, 0);
1616 ERROR(jail
->pakfire
, "Could not make the process dumpable: %m\n");
1620 // Don't drop any capabilities on setuid()
1621 r
= prctl(PR_SET_KEEPCAPS
, 1);
1623 ERROR(jail
->pakfire
, "Could not set PR_SET_KEEPCAPS: %m\n");
1628 uid_t uid
= getuid();
1629 gid_t gid
= getgid();
1632 uid_t euid
= geteuid();
1633 gid_t egid
= getegid();
1635 DEBUG(jail
->pakfire
, " UID: %d (effective %d)\n", uid
, euid
);
1636 DEBUG(jail
->pakfire
, " GID: %d (effective %d)\n", gid
, egid
);
1638 // Check if we are (effectively running as root)
1639 if (uid
|| gid
|| euid
|| egid
) {
1640 ERROR(jail
->pakfire
, "Child process is not running as root\n");
1644 const char* root
= pakfire_get_path(jail
->pakfire
);
1645 const char* arch
= pakfire_get_effective_arch(jail
->pakfire
);
1647 // Change mount propagation to slave to receive anything from the parent namespace
1648 r
= pakfire_mount_change_propagation(jail
->pakfire
, MS_SLAVE
, "/");
1652 // Make root a mountpoint in the new mount namespace
1653 r
= pakfire_mount_make_mounpoint(jail
->pakfire
, root
);
1657 // Change mount propagation to private
1658 r
= pakfire_mount_change_propagation(jail
->pakfire
, MS_PRIVATE
, root
);
1662 // Change root (unless root is /)
1663 if (!pakfire_on_root(jail
->pakfire
)) {
1665 r
= pakfire_jail_mount(jail
, ctx
);
1670 r
= pakfire_jail_switch_root(jail
, root
);
1676 unsigned long persona
= pakfire_arch_personality(arch
);
1678 r
= personality(persona
);
1680 ERROR(jail
->pakfire
, "Could not set personality (%x)\n", (unsigned int)persona
);
1686 if (!pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1687 r
= pakfire_jail_setup_loopback(jail
);
1694 DEBUG(jail
->pakfire
, "Setting nice level to %d\n", jail
->nice
);
1696 r
= setpriority(PRIO_PROCESS
, pid
, jail
->nice
);
1698 ERROR(jail
->pakfire
, "Could not set nice level: %m\n");
1703 // Close other end of log pipes
1704 close(ctx
->pipes
.log_INFO
[0]);
1705 close(ctx
->pipes
.log_ERROR
[0]);
1707 close(ctx
->pipes
.log_DEBUG
[0]);
1708 #endif /* ENABLE_DEBUG */
1710 // Connect standard input
1711 if (ctx
->pipes
.stdin
[0] >= 0) {
1712 r
= dup2(ctx
->pipes
.stdin
[0], STDIN_FILENO
);
1714 ERROR(jail
->pakfire
, "Could not connect fd %d to stdin: %m\n",
1715 ctx
->pipes
.stdin
[0]);
1721 // Connect standard output and error
1722 if (ctx
->pipes
.stdout
[1] >= 0 && ctx
->pipes
.stderr
[1] >= 0) {
1723 r
= dup2(ctx
->pipes
.stdout
[1], STDOUT_FILENO
);
1725 ERROR(jail
->pakfire
, "Could not connect fd %d to stdout: %m\n",
1726 ctx
->pipes
.stdout
[1]);
1731 r
= dup2(ctx
->pipes
.stderr
[1], STDERR_FILENO
);
1733 ERROR(jail
->pakfire
, "Could not connect fd %d to stderr: %m\n",
1734 ctx
->pipes
.stderr
[1]);
1739 // Close the pipe (as we have moved the original file descriptors)
1740 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdin
);
1741 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stdout
);
1742 pakfire_jail_close_pipe(jail
, ctx
->pipes
.stderr
);
1745 // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
1746 r
= pakfire_rlimit_reset_nofile(jail
->pakfire
);
1751 r
= pakfire_jail_set_capabilities(jail
);
1755 // Show capabilities
1756 r
= pakfire_jail_show_capabilities(jail
);
1761 r
= pakfire_jail_limit_syscalls(jail
);
1765 DEBUG(jail
->pakfire
, "Child process initialization done\n");
1766 DEBUG(jail
->pakfire
, "Launching command:\n");
1769 for (unsigned int i
= 0; argv
[i
]; i
++)
1770 DEBUG(jail
->pakfire
, " argv[%d] = %s\n", i
, argv
[i
]);
1773 r
= execvpe(argv
[0], (char**)argv
, jail
->env
);
1775 // Translate errno into regular exit code
1778 // Ignore if the command doesn't exist
1779 if (ctx
->flags
& PAKFIRE_JAIL_NOENT_OK
)
1790 ERROR(jail
->pakfire
, "Could not execve(%s): %m\n", argv
[0]);
1793 // We should not get here
1797 // Run a command in the jail
1798 static int __pakfire_jail_exec(struct pakfire_jail
* jail
, const char* argv
[],
1799 const int interactive
,
1800 pakfire_jail_communicate_in communicate_in
,
1801 pakfire_jail_communicate_out communicate_out
,
1802 void* data
, int flags
) {
1806 // Check if argv is valid
1807 if (!argv
|| !argv
[0]) {
1812 // Send any output to the default logger if no callback is set
1813 if (!communicate_out
)
1814 communicate_out
= pakfire_jail_default_log_callback
;
1816 // Initialize context for this call
1817 struct pakfire_jail_exec ctx
= {
1821 .stdin
= { -1, -1 },
1822 .stdout
= { -1, -1 },
1823 .stderr
= { -1, -1 },
1827 .in
= communicate_in
,
1828 .out
= communicate_out
,
1835 DEBUG(jail
->pakfire
, "Executing jail...\n");
1837 // Enable networking in interactive mode
1839 ctx
.flags
|= PAKFIRE_JAIL_HAS_NETWORKING
;
1842 Setup a file descriptor which can be used to notify the client that the parent
1843 has completed configuration.
1845 ctx
.completed_fd
= eventfd(0, EFD_CLOEXEC
);
1846 if (ctx
.completed_fd
< 0) {
1847 ERROR(jail
->pakfire
, "eventfd() failed: %m\n");
1851 // Create pipes to communicate with child process if we are not running interactively
1853 // stdin (only if callback is set)
1854 if (ctx
.communicate
.in
) {
1855 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdin
, 0);
1861 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stdout
, 0);
1866 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.stderr
, 0);
1871 // Setup pipes for logging
1873 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_INFO
, O_CLOEXEC
);
1878 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_ERROR
, O_CLOEXEC
);
1884 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_DEBUG
, O_CLOEXEC
);
1887 #endif /* ENABLE_DEBUG */
1889 // Configure child process
1890 struct clone_args args
= {
1900 .exit_signal
= SIGCHLD
,
1901 .pidfd
= (long long unsigned int)&ctx
.pidfd
,
1904 // Launch the process in a cgroup that is a leaf of the configured cgroup
1906 args
.flags
|= CLONE_INTO_CGROUP
;
1909 const char* uuid
= pakfire_jail_uuid(jail
);
1911 // Create a temporary cgroup
1912 r
= pakfire_cgroup_child(&ctx
.cgroup
, jail
->cgroup
, uuid
, 0);
1914 ERROR(jail
->pakfire
, "Could not create cgroup for jail: %m\n");
1918 // Clone into this cgroup
1919 args
.cgroup
= pakfire_cgroup_fd(ctx
.cgroup
);
1923 if (!pakfire_jail_exec_has_flag(&ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1924 args
.flags
|= CLONE_NEWNET
;
1927 // Fork this process
1928 ctx
.pid
= clone3(&args
, sizeof(args
));
1930 ERROR(jail
->pakfire
, "Could not clone: %m\n");
1934 } else if (ctx
.pid
== 0) {
1935 r
= pakfire_jail_child(jail
, &ctx
, argv
);
1940 r
= pakfire_jail_parent(jail
, &ctx
);
1944 DEBUG(jail
->pakfire
, "Waiting for PID %d to finish its work\n", ctx
.pid
);
1946 // Read output of the child process
1947 r
= pakfire_jail_wait(jail
, &ctx
);
1951 // Handle exit status
1952 switch (ctx
.status
.si_code
) {
1954 DEBUG(jail
->pakfire
, "The child process exited with code %d\n",
1955 ctx
.status
.si_status
);
1958 exit
= ctx
.status
.si_status
;
1962 ERROR(jail
->pakfire
, "The child process was killed\n");
1967 ERROR(jail
->pakfire
, "The child process terminated abnormally\n");
1970 // Log anything else
1972 ERROR(jail
->pakfire
, "Unknown child exit code: %d\n", ctx
.status
.si_code
);
1977 // Destroy the temporary cgroup (if any)
1979 // Read cgroup stats
1980 r
= pakfire_cgroup_stat(ctx
.cgroup
, &ctx
.cgroup_stats
);
1982 ERROR(jail
->pakfire
, "Could not read cgroup stats: %m\n");
1984 pakfire_cgroup_stat_dump(ctx
.cgroup
, &ctx
.cgroup_stats
);
1987 pakfire_cgroup_destroy(ctx
.cgroup
);
1988 pakfire_cgroup_unref(ctx
.cgroup
);
1991 // Close any file descriptors
1992 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdin
);
1993 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stdout
);
1994 pakfire_jail_close_pipe(jail
, ctx
.pipes
.stderr
);
1997 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_INFO
);
1998 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_ERROR
);
1999 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_DEBUG
);
2004 PAKFIRE_EXPORT
int pakfire_jail_exec(
2005 struct pakfire_jail
* jail
,
2007 pakfire_jail_communicate_in callback_in
,
2008 pakfire_jail_communicate_out callback_out
,
2009 void* data
, int flags
) {
2010 return __pakfire_jail_exec(jail
, argv
, 0, callback_in
, callback_out
, data
, flags
);
2013 static int pakfire_jail_exec_interactive(
2014 struct pakfire_jail
* jail
, const char* argv
[], int flags
) {
2017 // Setup interactive stuff
2018 r
= pakfire_jail_setup_interactive_env(jail
);
2022 return __pakfire_jail_exec(jail
, argv
, 1, NULL
, NULL
, NULL
, flags
);
2025 int pakfire_jail_exec_script(struct pakfire_jail
* jail
,
2029 pakfire_jail_communicate_in callback_in
,
2030 pakfire_jail_communicate_out callback_out
,
2032 char path
[PATH_MAX
];
2033 const char** argv
= NULL
;
2037 const char* root
= pakfire_get_path(jail
->pakfire
);
2039 // Write the scriptlet to disk
2040 r
= pakfire_path_join(path
, root
, PAKFIRE_TMP_DIR
"/pakfire-script.XXXXXX");
2044 // Create a temporary file
2045 f
= pakfire_mktemp(path
, 0700);
2047 ERROR(jail
->pakfire
, "Could not create temporary file: %m\n");
2051 DEBUG(jail
->pakfire
, "Writing script to %s:\n%.*s\n", path
, (int)size
, script
);
2054 r
= fprintf(f
, "%s", script
);
2056 ERROR(jail
->pakfire
, "Could not write script to file %s: %m\n", path
);
2063 ERROR(jail
->pakfire
, "Could not close script file %s: %m\n", path
);
2069 // Count how many arguments were passed
2070 unsigned int argc
= 1;
2072 for (const char** arg
= args
; *arg
; arg
++)
2076 argv
= calloc(argc
+ 1, sizeof(*argv
));
2078 ERROR(jail
->pakfire
, "Could not allocate argv: %m\n");
2083 argv
[0] = (root
) ? pakfire_path_relpath(root
, path
) : path
;
2086 for (unsigned int i
= 1; i
< argc
; i
++)
2087 argv
[i
] = args
[i
-1];
2090 r
= pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, 0);
2098 // Remove script from disk
2106 A convenience function that creates a new jail, runs the given command and destroys
2109 int pakfire_jail_run(struct pakfire
* pakfire
, const char* argv
[], int flags
, char** output
) {
2110 struct pakfire_jail
* jail
= NULL
;
2113 // Create a new jail
2114 r
= pakfire_jail_create(&jail
, pakfire
);
2118 // Execute the command
2119 r
= pakfire_jail_exec(jail
, argv
, NULL
, pakfire_jail_capture_stdout
, output
, 0);
2123 pakfire_jail_unref(jail
);
2128 int pakfire_jail_run_script(struct pakfire
* pakfire
,
2129 const char* script
, const size_t length
, const char* argv
[], int flags
) {
2130 struct pakfire_jail
* jail
= NULL
;
2133 // Create a new jail
2134 r
= pakfire_jail_create(&jail
, pakfire
);
2138 // Execute the command
2139 r
= pakfire_jail_exec_script(jail
, script
, length
, argv
, NULL
, NULL
, NULL
);
2143 pakfire_jail_unref(jail
);
2148 int pakfire_jail_shell(struct pakfire_jail
* jail
) {
2151 const char* argv
[] = {
2152 "/bin/bash", "--login", NULL
,
2155 // Execute /bin/bash
2156 r
= pakfire_jail_exec_interactive(jail
, argv
, 0);
2162 // Ignore any return codes from the shell
2166 static int pakfire_jail_run_if_possible(struct pakfire
* pakfire
, const char** argv
) {
2167 char path
[PATH_MAX
];
2170 r
= pakfire_path(pakfire
, path
, "%s", *argv
);
2174 // Check if the file is executable
2175 r
= access(path
, X_OK
);
2177 DEBUG(pakfire
, "%s is not executable. Skipping...\n", *argv
);
2181 return pakfire_jail_run(pakfire
, argv
, 0, NULL
);
2184 int pakfire_jail_ldconfig(struct pakfire
* pakfire
) {
2185 const char* argv
[] = {
2190 return pakfire_jail_run_if_possible(pakfire
, argv
);
2193 int pakfire_jail_run_systemd_tmpfiles(struct pakfire
* pakfire
) {
2194 const char* argv
[] = {
2195 "/usr/bin/systemd-tmpfiles",
2200 return pakfire_jail_run_if_possible(pakfire
, argv
);