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/timerfd.h>
39 #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/path.h>
60 #include <pakfire/private.h>
61 #include <pakfire/pwd.h>
62 #include <pakfire/string.h>
63 #include <pakfire/util.h>
65 #define BUFFER_SIZE 1024 * 64
66 #define ENVIRON_SIZE 128
67 #define EPOLL_MAX_EVENTS 2
68 #define MAX_MOUNTPOINTS 8
70 // The default environment that will be set for every command
71 static const struct environ
{
76 { "LANG", "C.utf-8" },
77 { "PATH", "/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin", },
80 // Tell everything that it is running inside a Pakfire container
81 { "container", "pakfire" },
85 struct pakfire_jail_mountpoint
{
86 char source
[PATH_MAX
];
87 char target
[PATH_MAX
];
92 struct pakfire_ctx
* ctx
;
93 struct pakfire
* pakfire
;
96 // A unique ID for each jail
98 char __uuid
[UUID_STR_LEN
];
104 struct itimerspec timeout
;
107 struct pakfire_cgroup
* cgroup
;
110 char* env
[ENVIRON_SIZE
];
113 struct pakfire_jail_mountpoint mountpoints
[MAX_MOUNTPOINTS
];
114 unsigned int num_mountpoints
;
117 struct pakfire_jail_callbacks
{
119 pakfire_jail_log_callback log
;
124 struct pakfire_log_buffer
{
125 char data
[BUFFER_SIZE
];
129 struct pakfire_jail_exec
{
132 // PID (of the child)
136 // Socket to pass FDs
139 // Process status (from waitid)
142 // FD to notify the client that the parent has finished initialization
146 struct pakfire_jail_pipes
{
152 #endif /* ENABLE_DEBUG */
156 struct pakfire_jail_communicate
{
157 pakfire_jail_communicate_in in
;
158 pakfire_jail_communicate_out out
;
163 struct pakfire_jail_buffers
{
164 struct pakfire_log_buffer stdout
;
165 struct pakfire_log_buffer stderr
;
168 struct pakfire_log_buffer log_INFO
;
169 struct pakfire_log_buffer log_ERROR
;
171 struct pakfire_log_buffer log_DEBUG
;
172 #endif /* ENABLE_DEBUG */
175 struct pakfire_cgroup
* cgroup
;
176 struct pakfire_cgroup_stats cgroup_stats
;
179 struct pakfire_jail_pty
{
180 // The path to the console
181 char console
[PATH_MAX
];
184 struct pakfire_jail_pty_master
{
187 enum pakfire_jail_pty_flags
{
188 PAKFIRE_JAIL_PTY_READY_TO_READ
= (1 << 0),
189 PAKFIRE_JAIL_PTY_READY_TO_WRITE
= (1 << 1),
194 struct pakfire_jail_pty_stdio
{
196 struct pakfire_log_buffer buffer
;
197 struct termios attrs
;
199 enum pakfire_jail_pty_flags flags
;
203 struct pakfire_jail_pty_stdio stdout
;
207 static int clone3(struct clone_args
* args
, size_t size
) {
208 return syscall(__NR_clone3
, args
, size
);
211 static int pidfd_send_signal(int pidfd
, int sig
, siginfo_t
* info
, unsigned int flags
) {
212 return syscall(SYS_pidfd_send_signal
, pidfd
, sig
, info
, flags
);
215 static int pivot_root(const char* new_root
, const char* old_root
) {
216 return syscall(SYS_pivot_root
, new_root
, old_root
);
219 static int pakfire_jail_exec_has_flag(
220 const struct pakfire_jail_exec
* ctx
, const enum pakfire_jail_exec_flags flag
) {
221 return ctx
->flags
& flag
;
224 static void pakfire_jail_free(struct pakfire_jail
* jail
) {
225 DEBUG(jail
->pakfire
, "Freeing jail at %p\n", jail
);
228 for (unsigned int i
= 0; jail
->env
[i
]; i
++)
232 pakfire_cgroup_unref(jail
->cgroup
);
234 pakfire_unref(jail
->pakfire
);
236 pakfire_ctx_unref(jail
->ctx
);
241 Passes any log messages on to the default pakfire log callback
243 static int pakfire_jail_default_log_callback(struct pakfire
* pakfire
, void* data
,
244 int priority
, const char* line
, size_t length
) {
247 INFO(pakfire
, "%s", line
);
251 ERROR(pakfire
, "%s", line
);
256 DEBUG(pakfire
, "%s", line
);
264 static const char* pakfire_jail_uuid(struct pakfire_jail
* jail
) {
266 uuid_unparse_lower(jail
->uuid
, jail
->__uuid
);
271 static int pakfire_jail_setup_interactive_env(struct pakfire_jail
* jail
) {
273 int r
= pakfire_jail_set_env(jail
, "PS1", "pakfire-jail \\w> ");
278 char* TERM
= secure_getenv("TERM");
280 r
= pakfire_jail_set_env(jail
, "TERM", TERM
);
286 char* LANG
= secure_getenv("LANG");
288 r
= pakfire_jail_set_env(jail
, "LANG", LANG
);
296 PAKFIRE_EXPORT
int pakfire_jail_create(struct pakfire_jail
** jail
, struct pakfire
* pakfire
) {
299 const char* arch
= pakfire_get_effective_arch(pakfire
);
301 // Allocate a new jail
302 struct pakfire_jail
* j
= calloc(1, sizeof(*j
));
307 j
->ctx
= pakfire_ctx(pakfire
);
310 j
->pakfire
= pakfire_ref(pakfire
);
312 // Initialize reference counter
315 // Generate a random UUID
316 uuid_generate_random(j
->uuid
);
318 DEBUG(j
->pakfire
, "Allocated new jail at %p\n", j
);
320 // Set the default logging callback
321 pakfire_jail_set_log_callback(j
, pakfire_jail_default_log_callback
, NULL
);
323 // Set default environment
324 for (const struct environ
* e
= ENV
; e
->key
; e
++) {
325 r
= pakfire_jail_set_env(j
, e
->key
, e
->val
);
330 // Enable all CPU features that CPU has to offer
331 if (!pakfire_arch_is_supported_by_host(arch
)) {
332 r
= pakfire_jail_set_env(j
, "QEMU_CPU", "max");
337 // Set container UUID
338 r
= pakfire_jail_set_env(j
, "container_uuid", pakfire_jail_uuid(j
));
342 // Disable systemctl to talk to systemd
343 if (!pakfire_on_root(j
->pakfire
)) {
344 r
= pakfire_jail_set_env(j
, "SYSTEMD_OFFLINE", "1");
354 pakfire_jail_free(j
);
359 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_ref(struct pakfire_jail
* jail
) {
365 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_unref(struct pakfire_jail
* jail
) {
366 if (--jail
->nrefs
> 0)
369 pakfire_jail_free(jail
);
375 PAKFIRE_EXPORT
void pakfire_jail_set_log_callback(struct pakfire_jail
* jail
,
376 pakfire_jail_log_callback callback
, void* data
) {
377 jail
->callbacks
.log
= callback
;
378 jail
->callbacks
.log_data
= data
;
383 PAKFIRE_EXPORT
int pakfire_jail_nice(struct pakfire_jail
* jail
, int nice
) {
384 // Check if nice level is in range
385 if (nice
< -19 || nice
> 20) {
396 int pakfire_jail_set_cgroup(struct pakfire_jail
* jail
, struct pakfire_cgroup
* cgroup
) {
397 // Free any previous cgroup
399 pakfire_cgroup_unref(jail
->cgroup
);
403 // Set any new cgroup
405 DEBUG(jail
->pakfire
, "Setting cgroup %p\n", cgroup
);
407 jail
->cgroup
= pakfire_cgroup_ref(cgroup
);
416 // Returns the length of the environment
417 static unsigned int pakfire_jail_env_length(struct pakfire_jail
* jail
) {
420 // Count everything in the environment
421 for (char** e
= jail
->env
; *e
; e
++)
427 // Finds an existing environment variable and returns its index or -1 if not found
428 static int pakfire_jail_find_env(struct pakfire_jail
* jail
, const char* key
) {
434 const size_t length
= strlen(key
);
436 for (unsigned int i
= 0; jail
->env
[i
]; i
++) {
437 if ((pakfire_string_startswith(jail
->env
[i
], key
)
438 && *(jail
->env
[i
] + length
) == '=')) {
447 // Returns the value of an environment variable or NULL
448 PAKFIRE_EXPORT
const char* pakfire_jail_get_env(struct pakfire_jail
* jail
,
450 int i
= pakfire_jail_find_env(jail
, key
);
454 return jail
->env
[i
] + strlen(key
) + 1;
457 // Sets an environment variable
458 PAKFIRE_EXPORT
int pakfire_jail_set_env(struct pakfire_jail
* jail
,
459 const char* key
, const char* value
) {
460 // Find the index where to write this value to
461 int i
= pakfire_jail_find_env(jail
, key
);
463 i
= pakfire_jail_env_length(jail
);
465 // Return -ENOSPC when the environment is full
466 if (i
>= ENVIRON_SIZE
) {
471 // Free any previous value
475 // Format and set environment variable
476 asprintf(&jail
->env
[i
], "%s=%s", key
, value
);
478 DEBUG(jail
->pakfire
, "Set environment variable: %s\n", jail
->env
[i
]);
483 // Imports an environment
484 PAKFIRE_EXPORT
int pakfire_jail_import_env(struct pakfire_jail
* jail
, const char* env
[]) {
492 // Copy environment variables
493 for (unsigned int i
= 0; env
[i
]; i
++) {
494 r
= pakfire_string_partition(env
[i
], "=", &key
, &val
);
499 r
= pakfire_jail_set_env(jail
, key
, val
);
516 PAKFIRE_EXPORT
int pakfire_jail_set_timeout(
517 struct pakfire_jail
* jail
, unsigned int timeout
) {
519 jail
->timeout
.it_value
.tv_sec
= timeout
;
522 DEBUG(jail
->pakfire
, "Timeout set to %u second(s)\n", timeout
);
524 DEBUG(jail
->pakfire
, "Timeout disabled\n");
529 static int pakfire_jail_create_timer(struct pakfire_jail
* jail
) {
532 // Nothing to do if no timeout has been set
533 if (!jail
->timeout
.it_value
.tv_sec
)
536 // Create a new timer
537 const int fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
539 ERROR(jail
->pakfire
, "Could not create timer: %m\n");
544 r
= timerfd_settime(fd
, 0, &jail
->timeout
, NULL
);
546 ERROR(jail
->pakfire
, "Could not arm timer: %m\n");
560 This function replaces any logging in the child process.
562 All log messages will be sent to the parent process through their respective pipes.
564 static void pakfire_jail_log_redirect(void* data
, int priority
, const char* file
,
565 int line
, const char* fn
, const char* format
, va_list args
) {
566 struct pakfire_jail_pipes
* pipes
= (struct pakfire_jail_pipes
*)data
;
571 fd
= pipes
->log_INFO
[1];
575 fd
= pipes
->log_ERROR
[1];
580 fd
= pipes
->log_DEBUG
[1];
582 #endif /* ENABLE_DEBUG */
584 // Ignore any messages of an unknown priority
589 // Send the log message
591 vdprintf(fd
, format
, args
);
594 static int pakfire_jail_log_buffer_is_full(const struct pakfire_log_buffer
* buffer
) {
595 return (sizeof(buffer
->data
) == buffer
->used
);
599 This function reads as much data as it can from the file descriptor.
600 If it finds a whole line in it, it will send it to the logger and repeat the process.
601 If not newline character is found, it will try to read more data until it finds one.
603 static int pakfire_jail_handle_log(struct pakfire_jail
* jail
,
604 struct pakfire_jail_exec
* ctx
, int priority
, int fd
,
605 struct pakfire_log_buffer
* buffer
, pakfire_jail_communicate_out callback
, void* data
) {
606 char line
[BUFFER_SIZE
+ 1];
608 // Fill up buffer from fd
609 if (buffer
->used
< sizeof(buffer
->data
)) {
610 ssize_t bytes_read
= read(fd
, buffer
->data
+ buffer
->used
,
611 sizeof(buffer
->data
) - buffer
->used
);
614 if (bytes_read
< 0) {
615 ERROR(jail
->pakfire
, "Could not read from fd %d: %m\n", fd
);
619 // Update buffer size
620 buffer
->used
+= bytes_read
;
623 // See if we have any lines that we can write
624 while (buffer
->used
) {
625 // Search for the end of the first line
626 char* eol
= memchr(buffer
->data
, '\n', buffer
->used
);
630 // If the buffer is full, we send the content to the logger and try again
631 // This should not happen in practise
632 if (pakfire_jail_log_buffer_is_full(buffer
)) {
633 DEBUG(jail
->pakfire
, "Logging buffer is full. Sending all content\n");
635 eol
= buffer
->data
+ sizeof(buffer
->data
) - 1;
637 // Otherwise we might have only read parts of the output
642 // Find the length of the string
643 size_t length
= eol
- buffer
->data
+ 1;
645 // Copy the line into the buffer
646 memcpy(line
, buffer
->data
, length
);
648 // Terminate the string
653 int r
= callback(jail
->pakfire
, data
, priority
, line
, length
);
655 ERROR(jail
->pakfire
, "The logging callback returned an error: %d\n", r
);
660 // Remove line from buffer
661 memmove(buffer
->data
, buffer
->data
+ length
, buffer
->used
- length
);
662 buffer
->used
-= length
;
669 static int pakfire_jail_stream_stdin(struct pakfire_jail
* jail
,
670 struct pakfire_jail_exec
* ctx
, const int fd
) {
673 // Nothing to do if there is no stdin callback set
674 if (!ctx
->communicate
.in
) {
675 DEBUG(jail
->pakfire
, "Callback for standard input is not set\n");
679 // Skip if the writing pipe has already been closed
680 if (ctx
->pipes
.stdin
[1] < 0)
683 DEBUG(jail
->pakfire
, "Streaming standard input...\n");
685 // Calling the callback
686 r
= ctx
->communicate
.in(jail
->pakfire
, ctx
->communicate
.data
, fd
);
688 DEBUG(jail
->pakfire
, "Standard input callback finished: %d\n", r
);
690 // The callback signaled that it has written everything
692 DEBUG(jail
->pakfire
, "Closing standard input pipe\n");
694 // Close the file-descriptor
697 // Reset the file-descriptor so it won't be closed again later
698 ctx
->pipes
.stdin
[1] = -1;
708 static int pakfire_jail_recv_fd(struct pakfire_jail
* jail
, int socket
, int* fd
) {
709 const size_t payload_length
= sizeof(fd
);
710 char buffer
[CMSG_SPACE(payload_length
)];
713 struct msghdr msg
= {
714 .msg_control
= buffer
,
715 .msg_controllen
= sizeof(buffer
),
718 // Receive the message
719 r
= recvmsg(socket
, &msg
, 0);
721 CTX_ERROR(jail
->ctx
, "Could not receive file descriptor: %s\n", strerror(errno
));
726 struct cmsghdr
* cmsg
= CMSG_FIRSTHDR(&msg
);
730 *fd
= *((int*)CMSG_DATA(cmsg
));
732 CTX_DEBUG(jail
->ctx
, "Received fd %d from socket %d\n", *fd
, socket
);
737 static int pakfire_jail_send_fd(struct pakfire_jail
* jail
, int socket
, int fd
) {
738 const size_t payload_length
= sizeof(fd
);
739 char buffer
[CMSG_SPACE(payload_length
)];
742 CTX_DEBUG(jail
->ctx
, "Sending fd %d to socket %d\n", fd
, socket
);
745 struct msghdr msg
= {
746 .msg_control
= buffer
,
747 .msg_controllen
= sizeof(buffer
),
751 struct cmsghdr
* cmsg
= CMSG_FIRSTHDR(&msg
);
752 cmsg
->cmsg_level
= SOL_SOCKET
;
753 cmsg
->cmsg_type
= SCM_RIGHTS
;
754 cmsg
->cmsg_len
= CMSG_LEN(payload_length
);
757 *((int*)CMSG_DATA(cmsg
)) = fd
;
760 r
= sendmsg(socket
, &msg
, 0);
762 CTX_ERROR(jail
->ctx
, "Could not send file descriptor: %s\n", strerror(errno
));
769 static int pakfire_jail_setup_pipe(struct pakfire_jail
* jail
, int (*fds
)[2], const int flags
) {
770 int r
= pipe2(*fds
, flags
);
772 ERROR(jail
->pakfire
, "Could not setup pipe: %m\n");
779 static void pakfire_jail_close_pipe(struct pakfire_jail
* jail
, int fds
[2]) {
780 for (unsigned int i
= 0; i
< 2; i
++)
786 This is a convenience function to fetch the reading end of a pipe and
787 closes the write end.
789 static int pakfire_jail_get_pipe_to_read(struct pakfire_jail
* jail
, int (*fds
)[2]) {
790 // Give the variables easier names to avoid confusion
791 int* fd_read
= &(*fds
)[0];
792 int* fd_write
= &(*fds
)[1];
794 // Close the write end of the pipe
795 if (*fd_write
>= 0) {
800 // Return the read end
807 static int pakfire_jail_get_pipe_to_write(struct pakfire_jail
* jail
, int (*fds
)[2]) {
808 // Give the variables easier names to avoid confusion
809 int* fd_read
= &(*fds
)[0];
810 int* fd_write
= &(*fds
)[1];
812 // Close the read end of the pipe
818 // Return the write end
825 static int pakfire_jail_log(struct pakfire
* pakfire
, void* data
, int priority
,
826 const char* line
, const size_t length
) {
827 // Pass everything to the parent logger
828 pakfire_log_condition(pakfire
, priority
, 0, "%.*s", (int)length
, line
);
833 static int pakfire_jail_epoll_add_fd(struct pakfire_jail
* jail
, int epollfd
, int fd
, int events
) {
834 struct epoll_event event
= {
835 .events
= events
|EPOLLHUP
,
843 int flags
= fcntl(fd
, F_GETFL
, 0);
845 // Set modified flags
846 r
= fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
);
848 CTX_ERROR(jail
->ctx
, "Could not set file descriptor %d into non-blocking mode: %s\n",
849 fd
, strerror(errno
));
853 // Add the file descriptor to the loop
854 r
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fd
, &event
);
856 ERROR(jail
->pakfire
, "Could not add file descriptor %d to epoll(): %s\n",
857 fd
, strerror(errno
));
866 static int pakfire_jail_enable_raw_mode(struct pakfire_jail
* jail
,
867 struct pakfire_jail_pty_stdio
* stdio
) {
868 struct termios raw_attrs
;
872 stdio
->fdflags
= fcntl(stdio
->fd
, F_GETFL
);
873 if (stdio
->fdflags
< 0) {
874 CTX_ERROR(jail
->ctx
, "Could not fetch flags from fd %d: %s\n",
875 stdio
->fd
, strerror(errno
));
879 // Fetch all attributes
880 r
= tcgetattr(stdio
->fd
, &stdio
->attrs
);
882 CTX_ERROR(jail
->ctx
, "Could not fetch terminal attributes from fd %d: %s\n",
883 stdio
->fd
, strerror(errno
));
887 // Copy all attributes
888 raw_attrs
= stdio
->attrs
;
891 cfmakeraw(&raw_attrs
);
895 raw_attrs
.c_oflag
= stdio
->attrs
.c_oflag
;
899 raw_attrs
.c_iflag
= stdio
->attrs
.c_iflag
;
900 raw_attrs
.c_lflag
= stdio
->attrs
.c_lflag
;
904 // Restore the attributes
905 r
= tcsetattr(stdio
->fd
, TCSANOW
, &raw_attrs
);
907 CTX_ERROR(jail
->ctx
, "Could not restore terminal attributes for fd %d: %s\n",
908 stdio
->fd
, strerror(errno
));
915 static int pakfire_jail_restore_attrs(struct pakfire_jail
* jail
,
916 const struct pakfire_jail_pty_stdio
* stdio
) {
920 r
= fcntl(stdio
->fd
, F_SETFL
, stdio
->fdflags
);
922 CTX_ERROR(jail
->ctx
, "Could not set flags for file descriptor %d: %s\n",
923 stdio
->fd
, strerror(errno
));
927 // Restore the attributes
928 r
= tcsetattr(stdio
->fd
, TCSANOW
, &stdio
->attrs
);
930 CTX_ERROR(jail
->ctx
, "Could not restore terminal attributes for %d, ignoring: %s\n",
931 stdio
->fd
, strerror(errno
));
938 static int pakfire_jail_setup_pty_forwarding(struct pakfire_jail
* jail
,
939 struct pakfire_jail_exec
* ctx
, const int epollfd
, const int fd
) {
943 CTX_DEBUG(jail
->ctx
, "Setting up PTY forwarding on fd %d\n", fd
);
945 // Store the file descriptor
946 ctx
->pty
.master
.fd
= fd
;
948 // Configure stdin/stdout
949 ctx
->pty
.stdin
.fd
= STDIN_FILENO
;
950 ctx
->pty
.stdout
.fd
= STDOUT_FILENO
;
953 r
= ioctl(ctx
->pty
.stdout
.fd
, TIOCGWINSZ
, &size
);
955 CTX_ERROR(jail
->ctx
, "Failed to determine terminal dimensions: %s\n", strerror(errno
));
960 r
= ioctl(ctx
->pty
.master
.fd
, TIOCSWINSZ
, &size
);
962 CTX_ERROR(jail
->ctx
, "Failed setting dimensions: %s\n", strerror(errno
));
966 // Enable RAW mode on standard input
967 r
= pakfire_jail_enable_raw_mode(jail
, &ctx
->pty
.stdin
);
971 // Enable RAW mode on standard output
972 r
= pakfire_jail_enable_raw_mode(jail
, &ctx
->pty
.stdout
);
976 // Add the master to the event loop
977 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.master
.fd
, EPOLLIN
|EPOLLOUT
|EPOLLET
);
981 // Add standard input to the event loop
982 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.stdin
.fd
, EPOLLIN
|EPOLLET
);
986 // Add standard output to the event loop
987 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.stdout
.fd
, EPOLLOUT
|EPOLLET
);
994 static int pakfire_jail_fill_buffer(struct pakfire_jail
* jail
, int fd
, struct pakfire_log_buffer
* buffer
) {
997 // Skip this if there is not space left in the buffer
998 if (buffer
->used
>= sizeof(buffer
->data
))
1002 r
= read(fd
, buffer
->data
+ buffer
->used
, sizeof(buffer
->data
) - buffer
->used
);
1016 } else if (r
== 0) {
1017 // XXX What to do here?
1027 static int pakfire_jail_drain_buffer(struct pakfire_jail
* jail
, int fd
, struct pakfire_log_buffer
* buffer
) {
1030 // Nothing to do if the buffer is empty
1035 r
= write(fd
, buffer
->data
, buffer
->used
);
1050 memmove(buffer
->data
, buffer
->data
+ r
, buffer
->used
- r
);
1058 static int pakfire_jail_forward_pty(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1061 // Read from standard input
1062 if (ctx
->pty
.stdin
.flags
& PAKFIRE_JAIL_PTY_READY_TO_READ
) {
1063 r
= pakfire_jail_fill_buffer(jail
, ctx
->pty
.stdin
.fd
, &ctx
->pty
.stdin
.buffer
);
1065 CTX_ERROR(jail
->ctx
, "Failed reading from standard input: %s\n", strerror(-r
));
1069 // We are done reading for now
1070 ctx
->pty
.stdin
.flags
&= ~PAKFIRE_JAIL_PTY_READY_TO_READ
;
1072 // But we may have data to write
1073 if (ctx
->pty
.stdin
.buffer
.used
)
1074 ctx
->pty
.master
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1077 // Write to the master
1078 if (ctx
->pty
.master
.flags
& PAKFIRE_JAIL_PTY_READY_TO_WRITE
) {
1079 r
= pakfire_jail_drain_buffer(jail
, ctx
->pty
.master
.fd
, &ctx
->pty
.stdin
.buffer
);
1081 CTX_ERROR(jail
->ctx
, "Failed writing to the PTY: %s\n", strerror(-r
));
1085 // We are done writing for now
1086 ctx
->pty
.master
.flags
&= ~PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1089 // Read from the master
1090 if (ctx
->pty
.master
.flags
& PAKFIRE_JAIL_PTY_READY_TO_READ
) {
1091 r
= pakfire_jail_fill_buffer(jail
, ctx
->pty
.master
.fd
, &ctx
->pty
.stdout
.buffer
);
1093 CTX_ERROR(jail
->ctx
, "Failed reading from the PTY: %s\n", strerror(-r
));
1097 // We are done reading for now
1098 ctx
->pty
.master
.flags
&= ~PAKFIRE_JAIL_PTY_READY_TO_READ
;
1100 // But we may have data to write
1101 if (ctx
->pty
.stdout
.buffer
.used
)
1102 ctx
->pty
.stdout
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1105 // Write to standard output
1106 if (ctx
->pty
.stdout
.flags
& PAKFIRE_JAIL_PTY_READY_TO_WRITE
) {
1107 r
= pakfire_jail_drain_buffer(jail
, ctx
->pty
.stdout
.fd
, &ctx
->pty
.stdout
.buffer
);
1109 CTX_ERROR(jail
->ctx
, "Failed writing to standard output: %s\n", strerror(-r
));
1113 // We are done writing for now
1114 ctx
->pty
.stdout
.flags
&= ~PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1120 static int pakfire_jail_wait(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1122 struct epoll_event events
[EPOLL_MAX_EVENTS
];
1126 // Fetch file descriptors from context
1127 const int pidfd
= ctx
->pidfd
;
1129 // Fetch the UNIX domain socket
1130 const int socket_recv
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->socket
);
1133 const int timerfd
= pakfire_jail_create_timer(jail
);
1136 const int log_INFO
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_INFO
);
1137 const int log_ERROR
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_ERROR
);
1139 const int log_DEBUG
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_DEBUG
);
1140 #endif /* ENABLE_DEBUG */
1142 // Make a list of all file descriptors we are interested in
1143 const struct pakfire_wait_fds
{
1148 { timerfd
, EPOLLIN
},
1151 { ctx
->pidfd
, EPOLLIN
},
1154 { log_INFO
, EPOLLIN
},
1155 { log_ERROR
, EPOLLIN
},
1157 { log_DEBUG
, EPOLLIN
},
1158 #endif /* ENABLE_DEBUG */
1160 // UNIX Domain Socket
1161 { socket_recv
, EPOLLIN
},
1168 epollfd
= epoll_create1(0);
1170 ERROR(jail
->pakfire
, "Could not initialize epoll(): %m\n");
1175 // Turn file descriptors into non-blocking mode and add them to epoll()
1176 for (const struct pakfire_wait_fds
* fd
= fds
; fd
->events
; fd
++) {
1177 // Skip fds which were not initialized
1181 // Add the FD to the event loop
1182 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, fd
->fd
, fd
->events
);
1189 // Loop for as long as the process is alive
1191 int num
= epoll_wait(epollfd
, events
, EPOLL_MAX_EVENTS
, -1);
1193 // Ignore if epoll_wait() has been interrupted
1197 ERROR(jail
->pakfire
, "epoll_wait() failed: %m\n");
1203 for (int i
= 0; i
< num
; i
++) {
1204 int e
= events
[i
].events
;
1205 int fd
= events
[i
].data
.fd
;
1207 // Handle PTY forwarding events
1208 if (ctx
->pty
.master
.fd
== fd
) {
1209 if (e
& (EPOLLIN
|EPOLLHUP
))
1210 ctx
->pty
.master
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_READ
;
1212 if (e
& (EPOLLOUT
|EPOLLHUP
))
1213 ctx
->pty
.master
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1216 r
= pakfire_jail_forward_pty(jail
, ctx
);
1218 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1222 // Handle standard input
1223 } else if (ctx
->pty
.stdin
.fd
== fd
) {
1224 if (e
& (EPOLLIN
|EPOLLHUP
))
1225 ctx
->pty
.stdin
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_READ
;
1228 r
= pakfire_jail_forward_pty(jail
, ctx
);
1230 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1234 // Handle standard output
1235 } else if (ctx
->pty
.stdout
.fd
== fd
) {
1236 if (e
& (EPOLLOUT
|EPOLLHUP
))
1237 ctx
->pty
.stdout
.flags
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1240 r
= pakfire_jail_forward_pty(jail
, ctx
);
1242 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1246 // Handle any changes to the PIDFD
1247 } else if (pidfd
== fd
) {
1249 // Call waidid() and store the result
1250 r
= waitid(P_PIDFD
, ctx
->pidfd
, &ctx
->status
, WEXITED
);
1252 ERROR(jail
->pakfire
, "waitid() failed: %m\n");
1256 // Mark that we have ended so that we will process the remaining
1257 // events from epoll() now, but won't restart the outer loop.
1261 // Handle timer events
1262 } else if (timerfd
== fd
) {
1264 DEBUG(jail
->pakfire
, "Timer event received\n");
1267 r
= read(timerfd
, garbage
, sizeof(garbage
));
1269 ERROR(jail
->pakfire
, "Could not disarm timer: %m\n");
1274 // Terminate the process if it hasn't already ended
1276 DEBUG(jail
->pakfire
, "Terminating process...\n");
1278 // Send SIGTERM to the process
1279 r
= pidfd_send_signal(pidfd
, SIGKILL
, NULL
, 0);
1281 ERROR(jail
->pakfire
, "Could not kill process: %m\n");
1287 // Handle socket messages
1288 } else if (socket_recv
== fd
) {
1290 // Receive the passed FD
1291 r
= pakfire_jail_recv_fd(jail
, socket_recv
, &fd
);
1295 // Setup PTY forwarding
1296 if (ctx
->pty
.master
.fd
< 0) {
1297 r
= pakfire_jail_setup_pty_forwarding(jail
, ctx
, epollfd
, fd
);
1299 CTX_ERROR(jail
->ctx
, "Failed setting up PTY forwarding: %s\n", strerror(-r
));
1305 // Handle log INFO messages
1306 } else if (log_INFO
== fd
) {
1308 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_INFO
, fd
,
1309 &ctx
->buffers
.log_INFO
, pakfire_jail_log
, NULL
);
1314 // Handle log ERROR messages
1315 } else if (log_ERROR
== fd
) {
1317 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_ERR
, fd
,
1318 &ctx
->buffers
.log_ERROR
, pakfire_jail_log
, NULL
);
1324 // Handle log DEBUG messages
1325 } else if (log_DEBUG
== fd
) {
1327 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_DEBUG
, fd
,
1328 &ctx
->buffers
.log_DEBUG
, pakfire_jail_log
, NULL
);
1332 #endif /* ENABLE_DEBUG */
1334 // Log a message for anything else
1336 DEBUG(jail
->pakfire
, "Received invalid file descriptor %d\n", fd
);
1340 // Check if any file descriptors have been closed
1342 // Remove the file descriptor
1343 r
= epoll_ctl(epollfd
, EPOLL_CTL_DEL
, fd
, NULL
);
1345 ERROR(jail
->pakfire
, "Could not remove closed file-descriptor %d: %m\n", fd
);
1358 // Restore any changed terminal attributes
1359 if (ctx
->pty
.stdin
.fd
>= 0)
1360 pakfire_jail_restore_attrs(jail
, &ctx
->pty
.stdin
);
1361 if (ctx
->pty
.stdout
.fd
>= 0)
1362 pakfire_jail_restore_attrs(jail
, &ctx
->pty
.stdout
);
1367 int pakfire_jail_capture_stdout(struct pakfire
* pakfire
, void* data
,
1368 int priority
, const char* line
, size_t length
) {
1369 char** output
= (char**)data
;
1372 // Append everything from stdout to a buffer
1373 if (output
&& priority
== LOG_INFO
) {
1374 r
= asprintf(output
, "%s%s", (output
&& *output
) ? *output
: "", line
);
1380 // Send everything else to the default logger
1381 return pakfire_jail_default_log_callback(pakfire
, NULL
, priority
, line
, length
);
1386 // Logs all capabilities of the current process
1387 static int pakfire_jail_show_capabilities(struct pakfire_jail
* jail
) {
1390 cap_flag_value_t value_e
;
1391 cap_flag_value_t value_i
;
1392 cap_flag_value_t value_p
;
1396 pid_t pid
= getpid();
1398 // Fetch all capabilities
1399 caps
= cap_get_proc();
1401 ERROR(jail
->pakfire
, "Could not fetch capabilities: %m\n");
1406 DEBUG(jail
->pakfire
, "Capabilities of PID %d:\n", pid
);
1408 // Iterate over all capabilities
1409 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1410 name
= cap_to_name(cap
);
1412 // Fetch effective value
1413 r
= cap_get_flag(caps
, cap
, CAP_EFFECTIVE
, &value_e
);
1417 // Fetch inheritable value
1418 r
= cap_get_flag(caps
, cap
, CAP_INHERITABLE
, &value_i
);
1422 // Fetch permitted value
1423 r
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &value_p
);
1427 DEBUG(jail
->pakfire
,
1428 " %-24s : %c%c%c\n",
1430 (value_e
== CAP_SET
) ? 'e' : '-',
1431 (value_i
== CAP_SET
) ? 'i' : '-',
1432 (value_p
== CAP_SET
) ? 'p' : '-'
1452 static int pakfire_jail_set_capabilities(struct pakfire_jail
* jail
) {
1457 // Fetch capabilities
1458 caps
= cap_get_proc();
1460 ERROR(jail
->pakfire
, "Could not read capabilities: %m\n");
1465 // Walk through all capabilities
1466 for (cap_value_t cap
= 0; cap_valid(cap
); cap
++) {
1467 cap_value_t _caps
[] = { cap
};
1469 // Fetch the name of the capability
1470 name
= cap_to_name(cap
);
1472 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, _caps
, CAP_SET
);
1474 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1478 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, _caps
, CAP_SET
);
1480 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1484 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, _caps
, CAP_SET
);
1486 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1495 // Restore all capabilities
1496 r
= cap_set_proc(caps
);
1498 ERROR(jail
->pakfire
, "Restoring capabilities failed: %m\n");
1502 // Add all capabilities to the ambient set
1503 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1504 name
= cap_to_name(cap
);
1506 // Raise the capability
1507 r
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
1509 ERROR(jail
->pakfire
, "Could not set ambient capability %s: %m\n", name
);
1532 static int pakfire_jail_limit_syscalls(struct pakfire_jail
* jail
) {
1533 const int syscalls
[] = {
1534 // The kernel's keyring isn't namespaced
1537 SCMP_SYS(request_key
),
1539 // Disable userfaultfd
1540 SCMP_SYS(userfaultfd
),
1542 // Disable perf which could leak a lot of information about the host
1543 SCMP_SYS(perf_event_open
),
1549 DEBUG(jail
->pakfire
, "Applying syscall filter...\n");
1551 // Setup a syscall filter which allows everything by default
1552 scmp_filter_ctx ctx
= seccomp_init(SCMP_ACT_ALLOW
);
1554 ERROR(jail
->pakfire
, "Could not setup seccomp filter: %m\n");
1559 for (const int* syscall
= syscalls
; *syscall
; syscall
++) {
1560 r
= seccomp_rule_add(ctx
, SCMP_ACT_ERRNO(EPERM
), *syscall
, 0);
1562 ERROR(jail
->pakfire
, "Could not configure syscall %d: %m\n", *syscall
);
1567 // Load syscall filter into the kernel
1568 r
= seccomp_load(ctx
);
1570 ERROR(jail
->pakfire
, "Could not load syscall filter into the kernel: %m\n");
1576 seccomp_release(ctx
);
1583 PAKFIRE_EXPORT
int pakfire_jail_bind(struct pakfire_jail
* jail
,
1584 const char* source
, const char* target
, int flags
) {
1585 struct pakfire_jail_mountpoint
* mp
= NULL
;
1588 // Check if there is any space left
1589 if (jail
->num_mountpoints
>= MAX_MOUNTPOINTS
) {
1594 // Check for valid inputs
1595 if (!source
|| !target
) {
1600 // Select the next free slot
1601 mp
= &jail
->mountpoints
[jail
->num_mountpoints
];
1604 r
= pakfire_string_set(mp
->source
, source
);
1606 ERROR(jail
->pakfire
, "Could not copy source: %m\n");
1611 r
= pakfire_string_set(mp
->target
, target
);
1613 ERROR(jail
->pakfire
, "Could not copy target: %m\n");
1620 // Increment counter
1621 jail
->num_mountpoints
++;
1626 static int pakfire_jail_mount_networking(struct pakfire_jail
* jail
) {
1629 const char* paths
[] = {
1635 // Bind-mount all paths read-only
1636 for (const char** path
= paths
; *path
; path
++) {
1637 r
= pakfire_bind(jail
->pakfire
, *path
, NULL
, MS_RDONLY
);
1640 // Ignore if we don't have permission
1655 Mounts everything that we require in the new namespace
1657 static int pakfire_jail_mount(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1658 struct pakfire_jail_mountpoint
* mp
= NULL
;
1662 // Enable loop devices
1663 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_LOOP_DEVICES
))
1664 flags
|= PAKFIRE_MOUNT_LOOP_DEVICES
;
1666 // Mount all default stuff
1667 r
= pakfire_mount_all(jail
->pakfire
, PAKFIRE_MNTNS_OUTER
, flags
);
1672 r
= pakfire_populate_dev(jail
->pakfire
, flags
);
1676 // Mount the interpreter (if needed)
1677 r
= pakfire_mount_interpreter(jail
->pakfire
);
1681 // Mount networking stuff
1682 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1683 r
= pakfire_jail_mount_networking(jail
);
1688 // Mount all custom stuff
1689 for (unsigned int i
= 0; i
< jail
->num_mountpoints
; i
++) {
1691 mp
= &jail
->mountpoints
[i
];
1694 r
= pakfire_bind(jail
->pakfire
, mp
->source
, mp
->target
, mp
->flags
);
1704 static int pakfire_jail_setup_loopback(struct pakfire_jail
* jail
) {
1705 struct nl_sock
* nl
= NULL
;
1706 struct nl_cache
* cache
= NULL
;
1707 struct rtnl_link
* link
= NULL
;
1708 struct rtnl_link
* change
= NULL
;
1711 DEBUG(jail
->pakfire
, "Setting up loopback...\n");
1713 // Allocate a netlink socket
1714 nl
= nl_socket_alloc();
1716 ERROR(jail
->pakfire
, "Could not allocate a netlink socket: %m\n");
1721 // Connect the socket
1722 r
= nl_connect(nl
, NETLINK_ROUTE
);
1724 ERROR(jail
->pakfire
, "Could not connect netlink socket: %s\n", nl_geterror(r
));
1728 // Allocate the netlink cache
1729 r
= rtnl_link_alloc_cache(nl
, AF_UNSPEC
, &cache
);
1731 ERROR(jail
->pakfire
, "Unable to allocate netlink cache: %s\n", nl_geterror(r
));
1735 // Fetch loopback interface
1736 link
= rtnl_link_get_by_name(cache
, "lo");
1738 ERROR(jail
->pakfire
, "Could not find lo interface. Ignoring.\n");
1743 // Allocate a new link
1744 change
= rtnl_link_alloc();
1746 ERROR(jail
->pakfire
, "Could not allocate change link\n");
1751 // Set the link to UP
1752 rtnl_link_set_flags(change
, IFF_UP
);
1754 // Apply any changes
1755 r
= rtnl_link_change(nl
, link
, change
, 0);
1757 ERROR(jail
->pakfire
, "Unable to activate loopback: %s\n", nl_geterror(r
));
1773 static int pakfire_jail_setup_uid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1774 char path
[PATH_MAX
];
1777 // Skip mapping anything when running on /
1778 if (pakfire_on_root(jail
->pakfire
))
1782 r
= pakfire_string_format(path
, "/proc/%d/uid_map", pid
);
1787 const uid_t uid
= pakfire_uid(jail
->pakfire
);
1790 const struct pakfire_subid
* subuid
= pakfire_subuid(jail
->pakfire
);
1794 /* When running as root, we will map the entire range.
1796 When running as a non-privileged user, we will map the root user inside the jail
1797 to the user's UID outside of the jail, and we will map the rest starting from one.
1802 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1803 "0 %lu %lu\n", subuid
->id
, subuid
->length
);
1805 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1806 "0 %lu 1\n1 %lu %lu\n", uid
, subuid
->id
, subuid
->length
);
1810 ERROR(jail
->pakfire
, "Could not map UIDs: %m\n");
1817 static int pakfire_jail_setup_gid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1818 char path
[PATH_MAX
];
1821 // Skip mapping anything when running on /
1822 if (pakfire_on_root(jail
->pakfire
))
1826 const gid_t gid
= pakfire_gid(jail
->pakfire
);
1829 const struct pakfire_subid
* subgid
= pakfire_subgid(jail
->pakfire
);
1834 r
= pakfire_string_format(path
, "/proc/%d/gid_map", pid
);
1840 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1841 "0 %lu %lu\n", subgid
->id
, subgid
->length
);
1843 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1844 "0 %lu 1\n1 %lu %lu\n", gid
, subgid
->id
, subgid
->length
);
1848 ERROR(jail
->pakfire
, "Could not map GIDs: %m\n");
1855 static int pakfire_jail_setgroups(struct pakfire_jail
* jail
, pid_t pid
) {
1856 char path
[PATH_MAX
];
1860 r
= pakfire_string_format(path
, "/proc/%d/setgroups", pid
);
1864 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0, "deny\n");
1866 CTX_ERROR(jail
->ctx
, "Could not set setgroups to deny: %s\n", strerror(errno
));
1873 static int pakfire_jail_send_signal(struct pakfire_jail
* jail
, int fd
) {
1874 const uint64_t val
= 1;
1877 DEBUG(jail
->pakfire
, "Sending signal...\n");
1879 // Write to the file descriptor
1880 r
= eventfd_write(fd
, val
);
1882 ERROR(jail
->pakfire
, "Could not send signal: %s\n", strerror(errno
));
1886 // Close the file descriptor
1892 static int pakfire_jail_wait_for_signal(struct pakfire_jail
* jail
, int fd
) {
1896 DEBUG(jail
->pakfire
, "Waiting for signal...\n");
1898 r
= eventfd_read(fd
, &val
);
1900 ERROR(jail
->pakfire
, "Error waiting for signal: %s\n", strerror(errno
));
1904 // Close the file descriptor
1911 Performs the initialisation that needs to happen in the parent part
1913 static int pakfire_jail_parent(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1916 // Setup UID mapping
1917 r
= pakfire_jail_setup_uid_mapping(jail
, ctx
->pid
);
1921 // Write "deny" to /proc/PID/setgroups
1922 r
= pakfire_jail_setgroups(jail
, ctx
->pid
);
1926 // Setup GID mapping
1927 r
= pakfire_jail_setup_gid_mapping(jail
, ctx
->pid
);
1931 // Parent has finished initialisation
1932 DEBUG(jail
->pakfire
, "Parent has finished initialization\n");
1934 // Send signal to client
1935 r
= pakfire_jail_send_signal(jail
, ctx
->completed_fd
);
1942 static int pakfire_jail_switch_root(struct pakfire_jail
* jail
, const char* root
) {
1945 // Change to the new root
1948 ERROR(jail
->pakfire
, "chdir(%s) failed: %m\n", root
);
1953 r
= pivot_root(".", ".");
1955 ERROR(jail
->pakfire
, "Failed changing into the new root directory %s: %m\n", root
);
1959 // Umount the old root
1960 r
= umount2(".", MNT_DETACH
);
1962 ERROR(jail
->pakfire
, "Could not umount the old root filesystem: %m\n");
1969 static int pakfire_jail_open_pty(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1972 // Allocate a new PTY
1973 ctx
->pty
.master
.fd
= posix_openpt(O_RDWR
|O_NONBLOCK
|O_NOCTTY
|O_CLOEXEC
);
1974 if (ctx
->pty
.master
.fd
< 0)
1978 r
= ptsname_r(ctx
->pty
.master
.fd
, ctx
->pty
.console
, sizeof(ctx
->pty
.console
));
1982 CTX_DEBUG(jail
->ctx
, "Allocated console at %s (%d)\n", ctx
->pty
.console
, ctx
->pty
.master
.fd
);
1984 // Unlock the master device
1985 r
= unlockpt(ctx
->pty
.master
.fd
);
1987 CTX_ERROR(jail
->ctx
, "Could not unlock the PTY: %s\n", strerror(errno
));
1992 r
= pakfire_symlink(jail
->ctx
, ctx
->pty
.console
, "/dev/console");
1999 static int pakfire_jail_setup_terminal(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
2003 // Open a new terminal
2004 fd
= open("/dev/console", O_RDWR
|O_NOCTTY
);
2006 CTX_ERROR(jail
->ctx
, "Failed to open a new terminal: %s\n", strerror(errno
));
2010 CTX_DEBUG(jail
->ctx
, "Opened a new terminal %d\n", fd
);
2012 // Connect the new terminal to standard input
2013 r
= dup2(fd
, STDIN_FILENO
);
2015 CTX_ERROR(jail
->ctx
, "Failed to open standard input: %s\n", strerror(errno
));
2019 // Connect the new terminal to standard output
2020 r
= dup2(fd
, STDOUT_FILENO
);
2022 CTX_ERROR(jail
->ctx
, "Failed to open standard output: %s\n", strerror(errno
));
2026 // Connect the new terminal to standard error
2027 r
= dup2(fd
, STDERR_FILENO
);
2029 CTX_ERROR(jail
->ctx
, "Failed to open standard error: %s\n", strerror(errno
));
2036 static int pakfire_jail_child(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
2037 const char* argv
[]) {
2040 // Redirect any logging to our log pipe
2041 pakfire_ctx_set_log_callback(jail
->ctx
, pakfire_jail_log_redirect
, &ctx
->pipes
);
2044 pid_t pid
= getpid();
2046 DEBUG(jail
->pakfire
, "Launched child process in jail with PID %d\n", pid
);
2048 // Wait for the parent to finish initialization
2049 r
= pakfire_jail_wait_for_signal(jail
, ctx
->completed_fd
);
2054 r
= prctl(PR_SET_PDEATHSIG
, SIGKILL
, 0, 0, 0);
2056 ERROR(jail
->pakfire
, "Could not configure to die with parent: %m\n");
2060 // Make this process dumpable
2061 r
= prctl (PR_SET_DUMPABLE
, 1, 0, 0, 0);
2063 ERROR(jail
->pakfire
, "Could not make the process dumpable: %m\n");
2067 // Don't drop any capabilities on setuid()
2068 r
= prctl(PR_SET_KEEPCAPS
, 1);
2070 ERROR(jail
->pakfire
, "Could not set PR_SET_KEEPCAPS: %m\n");
2075 uid_t uid
= getuid();
2076 gid_t gid
= getgid();
2079 uid_t euid
= geteuid();
2080 gid_t egid
= getegid();
2082 DEBUG(jail
->pakfire
, " UID: %u (effective %u)\n", uid
, euid
);
2083 DEBUG(jail
->pakfire
, " GID: %u (effective %u)\n", gid
, egid
);
2085 // Log all mountpoints
2086 pakfire_mount_list(jail
->ctx
);
2088 // Fail if we are not PID 1
2090 CTX_ERROR(jail
->ctx
, "Child process is not PID 1\n");
2094 // Fail if we are not running as root
2095 if (uid
|| gid
|| euid
|| egid
) {
2096 ERROR(jail
->pakfire
, "Child process is not running as root\n");
2100 const int socket_send
= pakfire_jail_get_pipe_to_write(jail
, &ctx
->socket
);
2102 // Mount all default stuff
2103 r
= pakfire_mount_all(jail
->pakfire
, PAKFIRE_MNTNS_INNER
, 0);
2107 const char* root
= pakfire_get_path(jail
->pakfire
);
2108 const char* arch
= pakfire_get_effective_arch(jail
->pakfire
);
2110 // Change mount propagation to slave to receive anything from the parent namespace
2111 r
= pakfire_mount_change_propagation(jail
->ctx
, "/", MS_SLAVE
);
2115 // Make root a mountpoint in the new mount namespace
2116 r
= pakfire_mount_make_mounpoint(jail
->pakfire
, root
);
2120 // Change mount propagation to private
2121 r
= pakfire_mount_change_propagation(jail
->ctx
, root
, MS_PRIVATE
);
2125 // Change root (unless root is /)
2126 if (!pakfire_on_root(jail
->pakfire
)) {
2128 r
= pakfire_jail_mount(jail
, ctx
);
2133 r
= pakfire_jail_switch_root(jail
, root
);
2139 unsigned long persona
= pakfire_arch_personality(arch
);
2141 r
= personality(persona
);
2143 ERROR(jail
->pakfire
, "Could not set personality (%x)\n", (unsigned int)persona
);
2149 if (!pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
2150 r
= pakfire_jail_setup_loopback(jail
);
2157 DEBUG(jail
->pakfire
, "Setting nice level to %d\n", jail
->nice
);
2159 r
= setpriority(PRIO_PROCESS
, pid
, jail
->nice
);
2161 ERROR(jail
->pakfire
, "Could not set nice level: %m\n");
2166 // Create a new session
2169 CTX_ERROR(jail
->ctx
, "Could not create a new session: %s\n", strerror(errno
));
2173 // Allocate a new PTY
2174 r
= pakfire_jail_open_pty(jail
, ctx
);
2176 CTX_ERROR(jail
->ctx
, "Could not allocate a new PTY: %s\n", strerror(-r
));
2180 // Send the PTY master to the parent process
2181 r
= pakfire_jail_send_fd(jail
, socket_send
, ctx
->pty
.master
.fd
);
2183 CTX_ERROR(jail
->ctx
, "Failed sending the PTY master to the parent: %s\n", strerror(-r
));
2187 // Setup the terminal
2188 r
= pakfire_jail_setup_terminal(jail
, ctx
);
2192 // Close the master of the PTY
2193 close(ctx
->pty
.master
.fd
);
2194 ctx
->pty
.master
.fd
= -1;
2199 // Close other end of log pipes
2200 close(ctx
->pipes
.log_INFO
[0]);
2201 close(ctx
->pipes
.log_ERROR
[0]);
2203 close(ctx
->pipes
.log_DEBUG
[0]);
2204 #endif /* ENABLE_DEBUG */
2206 // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
2207 r
= pakfire_rlimit_reset_nofile(jail
->pakfire
);
2212 r
= pakfire_jail_set_capabilities(jail
);
2216 // Show capabilities
2217 r
= pakfire_jail_show_capabilities(jail
);
2222 r
= pakfire_jail_limit_syscalls(jail
);
2226 DEBUG(jail
->pakfire
, "Child process initialization done\n");
2227 DEBUG(jail
->pakfire
, "Launching command:\n");
2230 for (unsigned int i
= 0; argv
[i
]; i
++)
2231 DEBUG(jail
->pakfire
, " argv[%u] = %s\n", i
, argv
[i
]);
2234 r
= execvpe(argv
[0], (char**)argv
, jail
->env
);
2236 // Translate errno into regular exit code
2239 // Ignore if the command doesn't exist
2240 if (ctx
->flags
& PAKFIRE_JAIL_NOENT_OK
)
2251 ERROR(jail
->pakfire
, "Could not execve(%s): %m\n", argv
[0]);
2254 // We should not get here
2258 // Run a command in the jail
2259 static int __pakfire_jail_exec(struct pakfire_jail
* jail
, const char* argv
[],
2260 const int interactive
,
2261 pakfire_jail_communicate_in communicate_in
,
2262 pakfire_jail_communicate_out communicate_out
,
2263 void* data
, int flags
) {
2267 // Check if argv is valid
2268 if (!argv
|| !argv
[0]) {
2273 // Initialize context for this call
2274 struct pakfire_jail_exec ctx
= {
2277 .socket
= { -1, -1 },
2280 .log_INFO
= { -1, -1 },
2281 .log_ERROR
= { -1, -1 },
2283 .log_DEBUG
= { -1, -1 },
2284 #endif /* ENABLE_DEBUG */
2288 .in
= communicate_in
,
2289 .out
= communicate_out
,
2309 DEBUG(jail
->pakfire
, "Executing jail...\n");
2311 // Enable networking in interactive mode
2313 ctx
.flags
|= PAKFIRE_JAIL_HAS_NETWORKING
;
2316 Setup a file descriptor which can be used to notify the client that the parent
2317 has completed configuration.
2319 ctx
.completed_fd
= eventfd(0, EFD_CLOEXEC
);
2320 if (ctx
.completed_fd
< 0) {
2321 ERROR(jail
->pakfire
, "eventfd() failed: %m\n");
2325 // Create a UNIX domain socket
2326 r
= socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ctx
.socket
);
2328 CTX_ERROR(jail
->ctx
, "Could not create UNIX socket: %s\n", strerror(errno
));
2333 // Setup pipes for logging
2335 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_INFO
, O_CLOEXEC
);
2340 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_ERROR
, O_CLOEXEC
);
2346 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_DEBUG
, O_CLOEXEC
);
2349 #endif /* ENABLE_DEBUG */
2351 // Configure child process
2352 struct clone_args args
= {
2362 .exit_signal
= SIGCHLD
,
2363 .pidfd
= (long long unsigned int)&ctx
.pidfd
,
2366 // Launch the process in a cgroup that is a leaf of the configured cgroup
2368 args
.flags
|= CLONE_INTO_CGROUP
;
2371 const char* uuid
= pakfire_jail_uuid(jail
);
2373 // Create a temporary cgroup
2374 r
= pakfire_cgroup_child(&ctx
.cgroup
, jail
->cgroup
, uuid
, 0);
2376 ERROR(jail
->pakfire
, "Could not create cgroup for jail: %m\n");
2380 // Clone into this cgroup
2381 args
.cgroup
= pakfire_cgroup_fd(ctx
.cgroup
);
2385 if (!pakfire_jail_exec_has_flag(&ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
2386 args
.flags
|= CLONE_NEWNET
;
2389 // Fork this process
2390 ctx
.pid
= clone3(&args
, sizeof(args
));
2392 ERROR(jail
->pakfire
, "Could not clone: %m\n");
2396 } else if (ctx
.pid
== 0) {
2397 r
= pakfire_jail_child(jail
, &ctx
, argv
);
2402 r
= pakfire_jail_parent(jail
, &ctx
);
2406 DEBUG(jail
->pakfire
, "Waiting for PID %d to finish its work\n", ctx
.pid
);
2408 // Read output of the child process
2409 r
= pakfire_jail_wait(jail
, &ctx
);
2413 // Handle exit status
2414 switch (ctx
.status
.si_code
) {
2416 DEBUG(jail
->pakfire
, "The child process exited with code %d\n",
2417 ctx
.status
.si_status
);
2420 exit
= ctx
.status
.si_status
;
2424 ERROR(jail
->pakfire
, "The child process was killed\n");
2429 ERROR(jail
->pakfire
, "The child process terminated abnormally\n");
2432 // Log anything else
2434 ERROR(jail
->pakfire
, "Unknown child exit code: %d\n", ctx
.status
.si_code
);
2439 // Destroy the temporary cgroup (if any)
2441 // Read cgroup stats
2442 pakfire_cgroup_stat(ctx
.cgroup
, &ctx
.cgroup_stats
);
2443 pakfire_cgroup_stat_dump(ctx
.cgroup
, &ctx
.cgroup_stats
);
2444 pakfire_cgroup_destroy(ctx
.cgroup
);
2445 pakfire_cgroup_unref(ctx
.cgroup
);
2448 // Close any file descriptors
2451 if (ctx
.pty
.master
.fd
>= 0)
2452 close(ctx
.pty
.master
.fd
);
2453 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_INFO
);
2454 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_ERROR
);
2456 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_DEBUG
);
2457 #endif /* ENABLE_DEBUG */
2458 pakfire_jail_close_pipe(jail
, ctx
.socket
);
2463 PAKFIRE_EXPORT
int pakfire_jail_exec(
2464 struct pakfire_jail
* jail
,
2466 pakfire_jail_communicate_in callback_in
,
2467 pakfire_jail_communicate_out callback_out
,
2468 void* data
, int flags
) {
2469 return __pakfire_jail_exec(jail
, argv
, 0, callback_in
, callback_out
, data
, flags
);
2472 static int pakfire_jail_exec_interactive(
2473 struct pakfire_jail
* jail
, const char* argv
[], int flags
) {
2476 // Setup interactive stuff
2477 r
= pakfire_jail_setup_interactive_env(jail
);
2481 return __pakfire_jail_exec(jail
, argv
, 1, NULL
, NULL
, NULL
, flags
);
2484 int pakfire_jail_exec_script(struct pakfire_jail
* jail
,
2488 pakfire_jail_communicate_in callback_in
,
2489 pakfire_jail_communicate_out callback_out
,
2491 char path
[PATH_MAX
];
2492 const char** argv
= NULL
;
2496 const char* root
= pakfire_get_path(jail
->pakfire
);
2498 // Write the scriptlet to disk
2499 r
= pakfire_path_append(path
, root
, PAKFIRE_TMP_DIR
"/pakfire-script.XXXXXX");
2503 // Create a temporary file
2504 f
= pakfire_mktemp(path
, 0700);
2506 ERROR(jail
->pakfire
, "Could not create temporary file: %m\n");
2510 DEBUG(jail
->pakfire
, "Writing script to %s:\n%.*s\n", path
, (int)size
, script
);
2513 r
= fprintf(f
, "%s", script
);
2515 ERROR(jail
->pakfire
, "Could not write script to file %s: %m\n", path
);
2522 ERROR(jail
->pakfire
, "Could not close script file %s: %m\n", path
);
2528 // Count how many arguments were passed
2529 unsigned int argc
= 1;
2531 for (const char** arg
= args
; *arg
; arg
++)
2535 argv
= calloc(argc
+ 1, sizeof(*argv
));
2537 ERROR(jail
->pakfire
, "Could not allocate argv: %m\n");
2542 argv
[0] = (root
) ? pakfire_path_relpath(root
, path
) : path
;
2545 for (unsigned int i
= 1; i
< argc
; i
++)
2546 argv
[i
] = args
[i
-1];
2549 r
= pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, 0);
2557 // Remove script from disk
2565 A convenience function that creates a new jail, runs the given command and destroys
2568 int pakfire_jail_run(struct pakfire
* pakfire
, const char* argv
[], int flags
, char** output
) {
2569 struct pakfire_jail
* jail
= NULL
;
2572 // Create a new jail
2573 r
= pakfire_jail_create(&jail
, pakfire
);
2577 // Execute the command
2578 r
= pakfire_jail_exec(jail
, argv
, NULL
, pakfire_jail_capture_stdout
, output
, 0);
2582 pakfire_jail_unref(jail
);
2587 int pakfire_jail_run_script(struct pakfire
* pakfire
,
2588 const char* script
, const size_t length
, const char* argv
[], int flags
) {
2589 struct pakfire_jail
* jail
= NULL
;
2592 // Create a new jail
2593 r
= pakfire_jail_create(&jail
, pakfire
);
2597 // Execute the command
2598 r
= pakfire_jail_exec_script(jail
, script
, length
, argv
, NULL
, NULL
, NULL
);
2602 pakfire_jail_unref(jail
);
2607 int pakfire_jail_shell(struct pakfire_jail
* jail
) {
2610 const char* argv
[] = {
2611 "/bin/bash", "--login", NULL
,
2614 // Execute /bin/bash
2615 r
= pakfire_jail_exec_interactive(jail
, argv
, 0);
2621 // Ignore any return codes from the shell
2625 static int pakfire_jail_run_if_possible(struct pakfire
* pakfire
, const char** argv
) {
2626 char path
[PATH_MAX
];
2629 r
= pakfire_path(pakfire
, path
, "%s", *argv
);
2633 // Check if the file is executable
2634 r
= access(path
, X_OK
);
2636 DEBUG(pakfire
, "%s is not executable. Skipping...\n", *argv
);
2640 return pakfire_jail_run(pakfire
, argv
, 0, NULL
);
2643 int pakfire_jail_ldconfig(struct pakfire
* pakfire
) {
2644 const char* argv
[] = {
2649 return pakfire_jail_run_if_possible(pakfire
, argv
);
2652 int pakfire_jail_run_systemd_tmpfiles(struct pakfire
* pakfire
) {
2653 const char* argv
[] = {
2654 "/usr/bin/systemd-tmpfiles",
2659 return pakfire_jail_run_if_possible(pakfire
, argv
);