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_log_buffer
{
86 char data
[BUFFER_SIZE
];
90 enum pakfire_jail_pty_io
{
91 PAKFIRE_JAIL_PTY_READY_TO_READ
= (1 << 0),
92 PAKFIRE_JAIL_PTY_READY_TO_WRITE
= (1 << 1),
95 struct pakfire_jail_pty_stdio
{
100 struct pakfire_log_buffer buffer
;
102 // Terminal Attributes
103 struct termios attrs
;
105 // File Descriptor Flags
109 enum pakfire_jail_pty_io io
;
112 struct pakfire_jail_mountpoint
{
113 char source
[PATH_MAX
];
114 char target
[PATH_MAX
];
118 struct pakfire_jail
{
119 struct pakfire_ctx
* ctx
;
120 struct pakfire
* pakfire
;
123 // A unique ID for each jail
125 char __uuid
[UUID_STR_LEN
];
131 struct itimerspec timeout
;
134 struct pakfire_cgroup
* cgroup
;
137 char* env
[ENVIRON_SIZE
];
140 struct pakfire_jail_mountpoint mountpoints
[MAX_MOUNTPOINTS
];
141 unsigned int num_mountpoints
;
144 struct pakfire_jail_exec
{
147 // PID (of the child)
151 // Socket to pass FDs
154 // Process status (from waitid)
157 // FD to notify the client that the parent has finished initialization
161 struct pakfire_jail_pipes
{
167 #endif /* ENABLE_DEBUG */
171 struct pakfire_jail_communicate
{
172 pakfire_jail_communicate_in in
;
173 pakfire_jail_communicate_out out
;
178 struct pakfire_jail_buffers
{
180 struct pakfire_log_buffer log_INFO
;
181 struct pakfire_log_buffer log_ERROR
;
183 struct pakfire_log_buffer log_DEBUG
;
184 #endif /* ENABLE_DEBUG */
187 struct pakfire_cgroup
* cgroup
;
188 struct pakfire_cgroup_stats cgroup_stats
;
191 struct pakfire_jail_pty
{
192 // The path to the console
193 char console
[PATH_MAX
];
196 struct pakfire_jail_pty_master
{
198 enum pakfire_jail_pty_io io
;
201 // Standard Input/Output
202 struct pakfire_jail_pty_stdio stdin
;
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
) {
245 struct pakfire_ctx
* ctx
= pakfire_ctx(pakfire
);
247 if (pakfire_ctx_get_log_level(ctx
) >= priority
)
248 pakfire_ctx_log(ctx
, priority
, NULL
, 0, NULL
, "%.*s", (int)length
, line
);
250 pakfire_ctx_unref(ctx
);
255 static const char* pakfire_jail_uuid(struct pakfire_jail
* jail
) {
257 uuid_unparse_lower(jail
->uuid
, jail
->__uuid
);
262 static int pakfire_jail_setup_interactive_env(struct pakfire_jail
* jail
) {
264 int r
= pakfire_jail_set_env(jail
, "PS1", "pakfire-jail \\w> ");
269 char* TERM
= secure_getenv("TERM");
271 r
= pakfire_jail_set_env(jail
, "TERM", TERM
);
277 char* LANG
= secure_getenv("LANG");
279 r
= pakfire_jail_set_env(jail
, "LANG", LANG
);
287 PAKFIRE_EXPORT
int pakfire_jail_create(struct pakfire_jail
** jail
, struct pakfire
* pakfire
) {
290 const char* arch
= pakfire_get_effective_arch(pakfire
);
292 // Allocate a new jail
293 struct pakfire_jail
* j
= calloc(1, sizeof(*j
));
298 j
->ctx
= pakfire_ctx(pakfire
);
301 j
->pakfire
= pakfire_ref(pakfire
);
303 // Initialize reference counter
306 // Generate a random UUID
307 uuid_generate_random(j
->uuid
);
309 DEBUG(j
->pakfire
, "Allocated new jail at %p\n", j
);
311 // Set default environment
312 for (const struct environ
* e
= ENV
; e
->key
; e
++) {
313 r
= pakfire_jail_set_env(j
, e
->key
, e
->val
);
318 // Enable all CPU features that CPU has to offer
319 if (!pakfire_arch_is_supported_by_host(arch
)) {
320 r
= pakfire_jail_set_env(j
, "QEMU_CPU", "max");
325 // Set container UUID
326 r
= pakfire_jail_set_env(j
, "container_uuid", pakfire_jail_uuid(j
));
330 // Disable systemctl to talk to systemd
331 if (!pakfire_on_root(j
->pakfire
)) {
332 r
= pakfire_jail_set_env(j
, "SYSTEMD_OFFLINE", "1");
342 pakfire_jail_free(j
);
347 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_ref(struct pakfire_jail
* jail
) {
353 PAKFIRE_EXPORT
struct pakfire_jail
* pakfire_jail_unref(struct pakfire_jail
* jail
) {
354 if (--jail
->nrefs
> 0)
357 pakfire_jail_free(jail
);
363 PAKFIRE_EXPORT
int pakfire_jail_nice(struct pakfire_jail
* jail
, int nice
) {
364 // Check if nice level is in range
365 if (nice
< -19 || nice
> 20) {
376 int pakfire_jail_set_cgroup(struct pakfire_jail
* jail
, struct pakfire_cgroup
* cgroup
) {
377 // Free any previous cgroup
379 pakfire_cgroup_unref(jail
->cgroup
);
383 // Set any new cgroup
385 DEBUG(jail
->pakfire
, "Setting cgroup %p\n", cgroup
);
387 jail
->cgroup
= pakfire_cgroup_ref(cgroup
);
396 // Returns the length of the environment
397 static unsigned int pakfire_jail_env_length(struct pakfire_jail
* jail
) {
400 // Count everything in the environment
401 for (char** e
= jail
->env
; *e
; e
++)
407 // Finds an existing environment variable and returns its index or -1 if not found
408 static int pakfire_jail_find_env(struct pakfire_jail
* jail
, const char* key
) {
414 const size_t length
= strlen(key
);
416 for (unsigned int i
= 0; jail
->env
[i
]; i
++) {
417 if ((pakfire_string_startswith(jail
->env
[i
], key
)
418 && *(jail
->env
[i
] + length
) == '=')) {
427 // Returns the value of an environment variable or NULL
428 PAKFIRE_EXPORT
const char* pakfire_jail_get_env(struct pakfire_jail
* jail
,
430 int i
= pakfire_jail_find_env(jail
, key
);
434 return jail
->env
[i
] + strlen(key
) + 1;
437 // Sets an environment variable
438 PAKFIRE_EXPORT
int pakfire_jail_set_env(struct pakfire_jail
* jail
,
439 const char* key
, const char* value
) {
440 // Find the index where to write this value to
441 int i
= pakfire_jail_find_env(jail
, key
);
443 i
= pakfire_jail_env_length(jail
);
445 // Return -ENOSPC when the environment is full
446 if (i
>= ENVIRON_SIZE
) {
451 // Free any previous value
455 // Format and set environment variable
456 asprintf(&jail
->env
[i
], "%s=%s", key
, value
);
458 DEBUG(jail
->pakfire
, "Set environment variable: %s\n", jail
->env
[i
]);
463 // Imports an environment
464 PAKFIRE_EXPORT
int pakfire_jail_import_env(struct pakfire_jail
* jail
, const char* env
[]) {
472 // Copy environment variables
473 for (unsigned int i
= 0; env
[i
]; i
++) {
474 r
= pakfire_string_partition(env
[i
], "=", &key
, &val
);
479 r
= pakfire_jail_set_env(jail
, key
, val
);
496 PAKFIRE_EXPORT
int pakfire_jail_set_timeout(
497 struct pakfire_jail
* jail
, unsigned int timeout
) {
499 jail
->timeout
.it_value
.tv_sec
= timeout
;
502 DEBUG(jail
->pakfire
, "Timeout set to %u second(s)\n", timeout
);
504 DEBUG(jail
->pakfire
, "Timeout disabled\n");
509 static int pakfire_jail_create_timer(struct pakfire_jail
* jail
) {
512 // Nothing to do if no timeout has been set
513 if (!jail
->timeout
.it_value
.tv_sec
)
516 // Create a new timer
517 const int fd
= timerfd_create(CLOCK_MONOTONIC
, 0);
519 ERROR(jail
->pakfire
, "Could not create timer: %m\n");
524 r
= timerfd_settime(fd
, 0, &jail
->timeout
, NULL
);
526 ERROR(jail
->pakfire
, "Could not arm timer: %m\n");
540 This function replaces any logging in the child process.
542 All log messages will be sent to the parent process through their respective pipes.
544 static void pakfire_jail_log_redirect(void* data
, int priority
, const char* file
,
545 int line
, const char* fn
, const char* format
, va_list args
) {
546 struct pakfire_jail_pipes
* pipes
= (struct pakfire_jail_pipes
*)data
;
551 fd
= pipes
->log_INFO
[1];
555 fd
= pipes
->log_ERROR
[1];
560 fd
= pipes
->log_DEBUG
[1];
562 #endif /* ENABLE_DEBUG */
564 // Ignore any messages of an unknown priority
569 // End if we do not have a file descriptor to write to
573 // Optionally log the function name
575 dprintf(fd
, "%s: ", fn
);
577 // Send the log message
578 vdprintf(fd
, format
, args
);
581 static int pakfire_jail_log_buffer_is_full(const struct pakfire_log_buffer
* buffer
) {
582 return (sizeof(buffer
->data
) == buffer
->used
);
585 static int pakfire_jail_fill_buffer(struct pakfire_jail
* jail
, int fd
, struct pakfire_log_buffer
* buffer
) {
588 // Skip this if there is not space left in the buffer
589 if (buffer
->used
>= sizeof(buffer
->data
))
593 r
= read(fd
, buffer
->data
+ buffer
->used
, sizeof(buffer
->data
) - buffer
->used
);
608 // XXX What to do here?
618 static int pakfire_jail_drain_buffer_with_callback(struct pakfire_jail
* jail
,
619 struct pakfire_log_buffer
* buffer
, int priority
, pakfire_jail_communicate_out callback
, void* data
) {
620 const char* eol
= NULL
;
623 while (buffer
->used
) {
624 // Search for the end of the first line
625 eol
= memchr(buffer
->data
, '\n', buffer
->used
);
629 // If the buffer is full, we send the entire content to make space.
630 if (pakfire_jail_log_buffer_is_full(buffer
)) {
631 CTX_DEBUG(jail
->ctx
, "Buffer is full. Sending all content\n");
633 eol
= buffer
->data
+ buffer
->used
- 1;
635 // Otherwise we might have only read parts of the output...
641 // Find the length of the string
642 const size_t length
= eol
- buffer
->data
+ 1;
645 r
= callback(jail
->pakfire
, data
, priority
, buffer
->data
, length
);
647 CTX_ERROR(jail
->ctx
, "The logging callback returned an error: %d\n", r
);
651 // Remove line from buffer
652 memmove(buffer
->data
, buffer
->data
+ length
, buffer
->used
- length
);
653 buffer
->used
-= length
;
659 static int pakfire_jail_drain_buffer(struct pakfire_jail
* jail
, int fd
, struct pakfire_log_buffer
* buffer
) {
662 // Nothing to do if the buffer is empty
666 // Do not try to write to an invalid file descriptor
671 r
= write(fd
, buffer
->data
, buffer
->used
);
686 memmove(buffer
->data
, buffer
->data
+ r
, buffer
->used
- r
);
695 This function reads as much data as it can from the file descriptor.
696 If it finds a whole line in it, it will send it to the logger and repeat the process.
697 If not newline character is found, it will try to read more data until it finds one.
699 static int pakfire_jail_handle_log(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
700 int priority
, int fd
, struct pakfire_log_buffer
* buffer
,
701 pakfire_jail_communicate_out callback
, void* data
) {
704 // Fill up buffer from fd
705 r
= pakfire_jail_fill_buffer(jail
, fd
, buffer
);
710 r
= pakfire_jail_drain_buffer_with_callback(jail
, buffer
, priority
, callback
, data
);
717 static int pakfire_jail_stream_stdin(struct pakfire_jail
* jail
,
718 struct pakfire_jail_exec
* ctx
, const int fd
) {
719 const char eof
= 0x04;
722 // Skip if the writing pipe has already been closed
726 CTX_DEBUG(jail
->ctx
, "Streaming standard input...\n");
728 // Calling the callback
729 r
= ctx
->communicate
.in(jail
->pakfire
, ctx
->communicate
.data
, fd
);
733 // The callback signaled that it has written everything
734 CTX_DEBUG(jail
->ctx
, "Closing standard input pipe\n");
737 r
= write(fd
, &eof
, sizeof(eof
));
739 CTX_ERROR(jail
->ctx
, "Could not write EOF: %s\n", strerror(errno
));
746 CTX_DEBUG(jail
->ctx
, "Standard input callback finished\n");
750 CTX_ERROR(jail
->ctx
, "Standard input callback failed: %s\n", strerror(-r
));
755 static int pakfire_jail_recv_fd(struct pakfire_jail
* jail
, int socket
, int* fd
) {
756 const size_t payload_length
= sizeof(fd
);
757 char buffer
[CMSG_SPACE(payload_length
)];
760 struct msghdr msg
= {
761 .msg_control
= buffer
,
762 .msg_controllen
= sizeof(buffer
),
765 // Receive the message
766 r
= recvmsg(socket
, &msg
, 0);
768 CTX_ERROR(jail
->ctx
, "Could not receive file descriptor: %s\n", strerror(errno
));
773 struct cmsghdr
* cmsg
= CMSG_FIRSTHDR(&msg
);
777 *fd
= *((int*)CMSG_DATA(cmsg
));
779 CTX_DEBUG(jail
->ctx
, "Received fd %d from socket %d\n", *fd
, socket
);
784 static int pakfire_jail_send_fd(struct pakfire_jail
* jail
, int socket
, int fd
) {
785 const size_t payload_length
= sizeof(fd
);
786 char buffer
[CMSG_SPACE(payload_length
)];
789 CTX_DEBUG(jail
->ctx
, "Sending fd %d to socket %d\n", fd
, socket
);
792 struct msghdr msg
= {
793 .msg_control
= buffer
,
794 .msg_controllen
= sizeof(buffer
),
798 struct cmsghdr
* cmsg
= CMSG_FIRSTHDR(&msg
);
799 cmsg
->cmsg_level
= SOL_SOCKET
;
800 cmsg
->cmsg_type
= SCM_RIGHTS
;
801 cmsg
->cmsg_len
= CMSG_LEN(payload_length
);
804 *((int*)CMSG_DATA(cmsg
)) = fd
;
807 r
= sendmsg(socket
, &msg
, 0);
809 CTX_ERROR(jail
->ctx
, "Could not send file descriptor: %s\n", strerror(errno
));
816 static int pakfire_jail_setup_pipe(struct pakfire_jail
* jail
, int (*fds
)[2], const int flags
) {
817 int r
= pipe2(*fds
, flags
);
819 ERROR(jail
->pakfire
, "Could not setup pipe: %m\n");
826 static void pakfire_jail_close_pipe(struct pakfire_jail
* jail
, int fds
[2]) {
827 for (unsigned int i
= 0; i
< 2; i
++)
833 This is a convenience function to fetch the reading end of a pipe and
834 closes the write end.
836 static int pakfire_jail_get_pipe_to_read(struct pakfire_jail
* jail
, int (*fds
)[2]) {
837 // Give the variables easier names to avoid confusion
838 int* fd_read
= &(*fds
)[0];
839 int* fd_write
= &(*fds
)[1];
841 // Close the write end of the pipe
842 if (*fd_write
>= 0) {
847 // Return the read end
854 static int pakfire_jail_get_pipe_to_write(struct pakfire_jail
* jail
, int (*fds
)[2]) {
855 // Give the variables easier names to avoid confusion
856 int* fd_read
= &(*fds
)[0];
857 int* fd_write
= &(*fds
)[1];
859 // Close the read end of the pipe
865 // Return the write end
872 static int pakfire_jail_epoll_add_fd(struct pakfire_jail
* jail
, int epollfd
, int fd
, int events
) {
873 struct epoll_event event
= {
874 .events
= events
|EPOLLHUP
,
882 int flags
= fcntl(fd
, F_GETFL
, 0);
884 // Set modified flags
885 r
= fcntl(fd
, F_SETFL
, flags
|O_NONBLOCK
);
887 CTX_ERROR(jail
->ctx
, "Could not set file descriptor %d into non-blocking mode: %s\n",
888 fd
, strerror(errno
));
892 // Add the file descriptor to the loop
893 r
= epoll_ctl(epollfd
, EPOLL_CTL_ADD
, fd
, &event
);
895 ERROR(jail
->pakfire
, "Could not add file descriptor %d to epoll(): %s\n",
896 fd
, strerror(errno
));
905 static int pakfire_jail_enable_raw_mode(struct pakfire_jail
* jail
,
906 struct pakfire_jail_pty_stdio
* stdio
) {
907 struct termios raw_attrs
;
910 // Skip if we don't know the file descriptor
914 // Skip everything if fd is not a TTY
915 if (!isatty(stdio
->fd
))
919 stdio
->flags
= fcntl(stdio
->fd
, F_GETFL
);
920 if (stdio
->flags
< 0) {
921 CTX_ERROR(jail
->ctx
, "Could not fetch flags from fd %d: %s\n",
922 stdio
->fd
, strerror(errno
));
926 // Fetch all attributes
927 r
= tcgetattr(stdio
->fd
, &stdio
->attrs
);
929 CTX_ERROR(jail
->ctx
, "Could not fetch terminal attributes from fd %d: %s\n",
930 stdio
->fd
, strerror(errno
));
934 // Copy all attributes
935 raw_attrs
= stdio
->attrs
;
938 cfmakeraw(&raw_attrs
);
942 raw_attrs
.c_oflag
= stdio
->attrs
.c_oflag
;
946 raw_attrs
.c_iflag
= stdio
->attrs
.c_iflag
;
947 raw_attrs
.c_lflag
= stdio
->attrs
.c_lflag
;
951 // Restore the attributes
952 r
= tcsetattr(stdio
->fd
, TCSANOW
, &raw_attrs
);
954 CTX_ERROR(jail
->ctx
, "Could not restore terminal attributes for fd %d: %s\n",
955 stdio
->fd
, strerror(errno
));
962 static int pakfire_jail_restore_attrs(struct pakfire_jail
* jail
,
963 const struct pakfire_jail_pty_stdio
* stdio
) {
966 // Skip if we don't know the file descriptor
970 // Skip everything if fd is not a TTY
971 if (!isatty(stdio
->fd
))
975 r
= fcntl(stdio
->fd
, F_SETFL
, stdio
->flags
);
977 CTX_ERROR(jail
->ctx
, "Could not set flags for file descriptor %d: %s\n",
978 stdio
->fd
, strerror(errno
));
982 // Restore the attributes
983 r
= tcsetattr(stdio
->fd
, TCSANOW
, &stdio
->attrs
);
985 CTX_ERROR(jail
->ctx
, "Could not restore terminal attributes for %d, ignoring: %s\n",
986 stdio
->fd
, strerror(errno
));
993 static int pakfire_jail_setup_pty_forwarding(struct pakfire_jail
* jail
,
994 struct pakfire_jail_exec
* ctx
, const int epollfd
, const int fd
) {
998 CTX_DEBUG(jail
->ctx
, "Setting up PTY forwarding on fd %d\n", fd
);
1000 // Store the file descriptor
1001 ctx
->pty
.master
.fd
= fd
;
1003 // Add the master to the event loop
1004 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.master
.fd
, EPOLLIN
|EPOLLOUT
|EPOLLET
);
1008 if (ctx
->flags
& PAKFIRE_JAIL_PTY_FORWARDING
) {
1009 // Configure stdin/stdout
1010 ctx
->pty
.stdin
.fd
= STDIN_FILENO
;
1011 ctx
->pty
.stdout
.fd
= STDOUT_FILENO
;
1014 if (isatty(ctx
->pty
.stdout
.fd
)) {
1015 r
= ioctl(ctx
->pty
.stdout
.fd
, TIOCGWINSZ
, &size
);
1017 CTX_ERROR(jail
->ctx
, "Failed to determine terminal dimensions: %s\n", strerror(errno
));
1022 r
= ioctl(ctx
->pty
.master
.fd
, TIOCSWINSZ
, &size
);
1024 CTX_ERROR(jail
->ctx
, "Failed setting dimensions: %s\n", strerror(errno
));
1029 // Enable RAW mode on standard input
1030 r
= pakfire_jail_enable_raw_mode(jail
, &ctx
->pty
.stdin
);
1034 // Enable RAW mode on standard output
1035 r
= pakfire_jail_enable_raw_mode(jail
, &ctx
->pty
.stdout
);
1039 // Add standard input to the event loop
1040 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.stdin
.fd
, EPOLLIN
|EPOLLET
);
1044 // Add standard output to the event loop
1045 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, ctx
->pty
.stdout
.fd
, EPOLLOUT
|EPOLLET
);
1053 static int pakfire_jail_forward_pty(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1056 while (ctx
->pty
.master
.io
|| ctx
->pty
.stdin
.io
|| ctx
->pty
.stdout
.io
) {
1057 // Read from standard input
1058 if (ctx
->pty
.stdin
.io
& PAKFIRE_JAIL_PTY_READY_TO_READ
) {
1059 r
= pakfire_jail_fill_buffer(jail
, ctx
->pty
.stdin
.fd
, &ctx
->pty
.stdin
.buffer
);
1061 CTX_ERROR(jail
->ctx
, "Failed reading from standard input: %s\n", strerror(-r
));
1065 // We are done reading for now
1066 ctx
->pty
.stdin
.io
&= ~PAKFIRE_JAIL_PTY_READY_TO_READ
;
1068 // But we may have data to write
1069 if (ctx
->pty
.stdin
.buffer
.used
)
1070 ctx
->pty
.master
.io
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1073 // Write to the master
1074 if (ctx
->pty
.master
.io
& PAKFIRE_JAIL_PTY_READY_TO_WRITE
) {
1075 if (ctx
->communicate
.in
) {
1076 r
= pakfire_jail_stream_stdin(jail
, ctx
, ctx
->pty
.master
.fd
);
1081 r
= pakfire_jail_drain_buffer(jail
, ctx
->pty
.master
.fd
, &ctx
->pty
.stdin
.buffer
);
1083 CTX_ERROR(jail
->ctx
, "Failed writing to the PTY: %s\n", strerror(-r
));
1088 // We are done writing for now
1089 ctx
->pty
.master
.io
&= ~PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1092 // Read from the master
1093 if (ctx
->pty
.master
.io
& PAKFIRE_JAIL_PTY_READY_TO_READ
) {
1094 r
= pakfire_jail_fill_buffer(jail
, ctx
->pty
.master
.fd
, &ctx
->pty
.stdout
.buffer
);
1096 CTX_ERROR(jail
->ctx
, "Failed reading from the PTY: %s\n", strerror(-r
));
1100 // We are done reading for now
1101 ctx
->pty
.master
.io
&= ~PAKFIRE_JAIL_PTY_READY_TO_READ
;
1103 // But we may have data to write
1104 if (ctx
->pty
.stdout
.buffer
.used
)
1105 ctx
->pty
.stdout
.io
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1108 // Write to standard output
1109 if (ctx
->pty
.stdout
.flags
& PAKFIRE_JAIL_PTY_READY_TO_WRITE
) {
1110 // If we have a callback, we will send any output to the callback
1111 if (ctx
->communicate
.out
) {
1112 r
= pakfire_jail_drain_buffer_with_callback(jail
, &ctx
->pty
.stdout
.buffer
,
1113 LOG_INFO
, ctx
->communicate
.out
, ctx
->communicate
.data
);
1117 // If we have a file descriptor, we will forward any output
1118 } else if (ctx
->pty
.stdout
.fd
>= 0) {
1119 r
= pakfire_jail_drain_buffer(jail
, ctx
->pty
.stdout
.fd
, &ctx
->pty
.stdout
.buffer
);
1121 CTX_ERROR(jail
->ctx
, "Failed writing to standard output: %s\n", strerror(-r
));
1125 // Otherwise send the output to the default logger
1127 r
= pakfire_jail_drain_buffer_with_callback(jail
, &ctx
->pty
.stdout
.buffer
,
1128 LOG_INFO
, pakfire_jail_default_log_callback
, NULL
);
1133 // We are done writing for now
1134 ctx
->pty
.stdout
.io
&= ~PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1141 static int pakfire_jail_wait(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1143 struct epoll_event events
[EPOLL_MAX_EVENTS
];
1147 // Fetch file descriptors from context
1148 const int pidfd
= ctx
->pidfd
;
1150 // Fetch the UNIX domain socket
1151 const int socket_recv
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->socket
);
1154 const int timerfd
= pakfire_jail_create_timer(jail
);
1157 const int log_INFO
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_INFO
);
1158 const int log_ERROR
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_ERROR
);
1160 const int log_DEBUG
= pakfire_jail_get_pipe_to_read(jail
, &ctx
->pipes
.log_DEBUG
);
1161 #endif /* ENABLE_DEBUG */
1163 // Make a list of all file descriptors we are interested in
1164 const struct pakfire_wait_fds
{
1169 { timerfd
, EPOLLIN
},
1172 { ctx
->pidfd
, EPOLLIN
},
1175 { log_INFO
, EPOLLIN
},
1176 { log_ERROR
, EPOLLIN
},
1178 { log_DEBUG
, EPOLLIN
},
1179 #endif /* ENABLE_DEBUG */
1181 // UNIX Domain Socket
1182 { socket_recv
, EPOLLIN
},
1189 epollfd
= epoll_create1(0);
1191 ERROR(jail
->pakfire
, "Could not initialize epoll(): %m\n");
1196 // Turn file descriptors into non-blocking mode and add them to epoll()
1197 for (const struct pakfire_wait_fds
* fd
= fds
; fd
->events
; fd
++) {
1198 // Skip fds which were not initialized
1202 // Add the FD to the event loop
1203 r
= pakfire_jail_epoll_add_fd(jail
, epollfd
, fd
->fd
, fd
->events
);
1210 // Loop for as long as the process is alive
1212 int num
= epoll_wait(epollfd
, events
, EPOLL_MAX_EVENTS
, -1);
1214 // Ignore if epoll_wait() has been interrupted
1218 ERROR(jail
->pakfire
, "epoll_wait() failed: %m\n");
1224 for (int i
= 0; i
< num
; i
++) {
1225 int e
= events
[i
].events
;
1226 int fd
= events
[i
].data
.fd
;
1228 // Handle PTY forwarding events
1229 if (ctx
->pty
.master
.fd
== fd
) {
1230 if (e
& (EPOLLIN
|EPOLLHUP
))
1231 ctx
->pty
.master
.io
|= PAKFIRE_JAIL_PTY_READY_TO_READ
;
1233 if (e
& (EPOLLOUT
|EPOLLHUP
))
1234 ctx
->pty
.master
.io
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1237 r
= pakfire_jail_forward_pty(jail
, ctx
);
1239 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1243 // Handle standard input
1244 } else if (ctx
->pty
.stdin
.fd
== fd
) {
1245 if (e
& (EPOLLIN
|EPOLLHUP
))
1246 ctx
->pty
.stdin
.io
|= PAKFIRE_JAIL_PTY_READY_TO_READ
;
1249 r
= pakfire_jail_forward_pty(jail
, ctx
);
1251 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1255 // Handle standard output
1256 } else if (ctx
->pty
.stdout
.fd
== fd
) {
1257 if (e
& (EPOLLOUT
|EPOLLHUP
))
1258 ctx
->pty
.stdout
.io
|= PAKFIRE_JAIL_PTY_READY_TO_WRITE
;
1261 r
= pakfire_jail_forward_pty(jail
, ctx
);
1263 CTX_ERROR(jail
->ctx
, "Failed forwarding the PTY: %s\n", strerror(-r
));
1267 // Handle any changes to the PIDFD
1268 } else if (pidfd
== fd
) {
1270 // Call waidid() and store the result
1271 r
= waitid(P_PIDFD
, ctx
->pidfd
, &ctx
->status
, WEXITED
);
1273 ERROR(jail
->pakfire
, "waitid() failed: %m\n");
1277 // Mark that we have ended so that we will process the remaining
1278 // events from epoll() now, but won't restart the outer loop.
1282 // Handle timer events
1283 } else if (timerfd
== fd
) {
1285 DEBUG(jail
->pakfire
, "Timer event received\n");
1288 r
= read(timerfd
, garbage
, sizeof(garbage
));
1290 ERROR(jail
->pakfire
, "Could not disarm timer: %m\n");
1295 // Terminate the process if it hasn't already ended
1297 DEBUG(jail
->pakfire
, "Terminating process...\n");
1299 // Send SIGTERM to the process
1300 r
= pidfd_send_signal(pidfd
, SIGKILL
, NULL
, 0);
1302 ERROR(jail
->pakfire
, "Could not kill process: %m\n");
1308 // Handle socket messages
1309 } else if (socket_recv
== fd
) {
1311 // Receive the passed FD
1312 r
= pakfire_jail_recv_fd(jail
, socket_recv
, &fd
);
1316 // Setup PTY forwarding
1317 if (ctx
->pty
.master
.fd
< 0) {
1318 r
= pakfire_jail_setup_pty_forwarding(jail
, ctx
, epollfd
, fd
);
1320 CTX_ERROR(jail
->ctx
, "Failed setting up PTY forwarding: %s\n", strerror(-r
));
1326 // Handle log INFO messages
1327 } else if (log_INFO
== fd
) {
1329 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_INFO
, fd
,
1330 &ctx
->buffers
.log_INFO
, pakfire_jail_default_log_callback
, NULL
);
1335 // Handle log ERROR messages
1336 } else if (log_ERROR
== fd
) {
1338 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_ERR
, fd
,
1339 &ctx
->buffers
.log_ERROR
, pakfire_jail_default_log_callback
, NULL
);
1345 // Handle log DEBUG messages
1346 } else if (log_DEBUG
== fd
) {
1348 r
= pakfire_jail_handle_log(jail
, ctx
, LOG_DEBUG
, fd
,
1349 &ctx
->buffers
.log_DEBUG
, pakfire_jail_default_log_callback
, NULL
);
1353 #endif /* ENABLE_DEBUG */
1355 // Log a message for anything else
1357 DEBUG(jail
->pakfire
, "Received invalid file descriptor %d\n", fd
);
1361 // Check if any file descriptors have been closed
1363 // Remove the file descriptor
1364 r
= epoll_ctl(epollfd
, EPOLL_CTL_DEL
, fd
, NULL
);
1366 ERROR(jail
->pakfire
, "Could not remove closed file-descriptor %d: %m\n", fd
);
1379 // Restore any changed terminal attributes
1380 if (ctx
->pty
.stdin
.fd
>= 0)
1381 pakfire_jail_restore_attrs(jail
, &ctx
->pty
.stdin
);
1382 if (ctx
->pty
.stdout
.fd
>= 0)
1383 pakfire_jail_restore_attrs(jail
, &ctx
->pty
.stdout
);
1388 int pakfire_jail_capture_stdout(struct pakfire
* pakfire
, void* data
,
1389 int priority
, const char* line
, size_t length
) {
1390 char** output
= (char**)data
;
1393 // Append everything from stdout to a buffer
1394 if (output
&& priority
== LOG_INFO
) {
1395 r
= asprintf(output
, "%s%.*s", (output
&& *output
) ? *output
: "", (int)length
, line
);
1402 // Send everything else to the default logger
1403 return pakfire_jail_default_log_callback(pakfire
, NULL
, priority
, line
, length
);
1408 // Logs all capabilities of the current process
1409 static int pakfire_jail_show_capabilities(struct pakfire_jail
* jail
) {
1412 cap_flag_value_t value_e
;
1413 cap_flag_value_t value_i
;
1414 cap_flag_value_t value_p
;
1418 pid_t pid
= getpid();
1420 // Fetch all capabilities
1421 caps
= cap_get_proc();
1423 ERROR(jail
->pakfire
, "Could not fetch capabilities: %m\n");
1428 DEBUG(jail
->pakfire
, "Capabilities of PID %d:\n", pid
);
1430 // Iterate over all capabilities
1431 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1432 name
= cap_to_name(cap
);
1434 // Fetch effective value
1435 r
= cap_get_flag(caps
, cap
, CAP_EFFECTIVE
, &value_e
);
1439 // Fetch inheritable value
1440 r
= cap_get_flag(caps
, cap
, CAP_INHERITABLE
, &value_i
);
1444 // Fetch permitted value
1445 r
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &value_p
);
1449 DEBUG(jail
->pakfire
,
1450 " %-24s : %c%c%c\n",
1452 (value_e
== CAP_SET
) ? 'e' : '-',
1453 (value_i
== CAP_SET
) ? 'i' : '-',
1454 (value_p
== CAP_SET
) ? 'p' : '-'
1474 static int pakfire_jail_set_capabilities(struct pakfire_jail
* jail
) {
1479 // Fetch capabilities
1480 caps
= cap_get_proc();
1482 ERROR(jail
->pakfire
, "Could not read capabilities: %m\n");
1487 // Walk through all capabilities
1488 for (cap_value_t cap
= 0; cap_valid(cap
); cap
++) {
1489 cap_value_t _caps
[] = { cap
};
1491 // Fetch the name of the capability
1492 name
= cap_to_name(cap
);
1494 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, _caps
, CAP_SET
);
1496 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1500 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, _caps
, CAP_SET
);
1502 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1506 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, _caps
, CAP_SET
);
1508 ERROR(jail
->pakfire
, "Could not set %s: %m\n", name
);
1517 // Restore all capabilities
1518 r
= cap_set_proc(caps
);
1520 ERROR(jail
->pakfire
, "Restoring capabilities failed: %m\n");
1524 // Add all capabilities to the ambient set
1525 for (unsigned int cap
= 0; cap_valid(cap
); cap
++) {
1526 name
= cap_to_name(cap
);
1528 // Raise the capability
1529 r
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
1531 ERROR(jail
->pakfire
, "Could not set ambient capability %s: %m\n", name
);
1554 static int pakfire_jail_limit_syscalls(struct pakfire_jail
* jail
) {
1555 const int syscalls
[] = {
1556 // The kernel's keyring isn't namespaced
1559 SCMP_SYS(request_key
),
1561 // Disable userfaultfd
1562 SCMP_SYS(userfaultfd
),
1564 // Disable perf which could leak a lot of information about the host
1565 SCMP_SYS(perf_event_open
),
1571 DEBUG(jail
->pakfire
, "Applying syscall filter...\n");
1573 // Setup a syscall filter which allows everything by default
1574 scmp_filter_ctx ctx
= seccomp_init(SCMP_ACT_ALLOW
);
1576 ERROR(jail
->pakfire
, "Could not setup seccomp filter: %m\n");
1581 for (const int* syscall
= syscalls
; *syscall
; syscall
++) {
1582 r
= seccomp_rule_add(ctx
, SCMP_ACT_ERRNO(EPERM
), *syscall
, 0);
1584 ERROR(jail
->pakfire
, "Could not configure syscall %d: %m\n", *syscall
);
1589 // Load syscall filter into the kernel
1590 r
= seccomp_load(ctx
);
1592 ERROR(jail
->pakfire
, "Could not load syscall filter into the kernel: %m\n");
1598 seccomp_release(ctx
);
1605 PAKFIRE_EXPORT
int pakfire_jail_bind(struct pakfire_jail
* jail
,
1606 const char* source
, const char* target
, int flags
) {
1607 struct pakfire_jail_mountpoint
* mp
= NULL
;
1610 // Check if there is any space left
1611 if (jail
->num_mountpoints
>= MAX_MOUNTPOINTS
) {
1616 // Check for valid inputs
1617 if (!source
|| !target
) {
1622 // Select the next free slot
1623 mp
= &jail
->mountpoints
[jail
->num_mountpoints
];
1626 r
= pakfire_string_set(mp
->source
, source
);
1628 ERROR(jail
->pakfire
, "Could not copy source: %m\n");
1633 r
= pakfire_string_set(mp
->target
, target
);
1635 ERROR(jail
->pakfire
, "Could not copy target: %m\n");
1642 // Increment counter
1643 jail
->num_mountpoints
++;
1648 static int pakfire_jail_mount_networking(struct pakfire_jail
* jail
) {
1651 const char* paths
[] = {
1657 // Bind-mount all paths read-only
1658 for (const char** path
= paths
; *path
; path
++) {
1659 r
= pakfire_bind(jail
->pakfire
, *path
, NULL
, MS_RDONLY
);
1662 // Ignore if we don't have permission
1677 Mounts everything that we require in the new namespace
1679 static int pakfire_jail_mount(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1680 struct pakfire_jail_mountpoint
* mp
= NULL
;
1684 // Enable loop devices
1685 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_LOOP_DEVICES
))
1686 flags
|= PAKFIRE_MOUNT_LOOP_DEVICES
;
1688 // Mount all default stuff
1689 r
= pakfire_mount_all(jail
->pakfire
, PAKFIRE_MNTNS_OUTER
, flags
);
1694 r
= pakfire_populate_dev(jail
->pakfire
, flags
);
1698 // Mount the interpreter (if needed)
1699 r
= pakfire_mount_interpreter(jail
->pakfire
);
1703 // Mount networking stuff
1704 if (pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
1705 r
= pakfire_jail_mount_networking(jail
);
1710 // Mount all custom stuff
1711 for (unsigned int i
= 0; i
< jail
->num_mountpoints
; i
++) {
1713 mp
= &jail
->mountpoints
[i
];
1716 r
= pakfire_bind(jail
->pakfire
, mp
->source
, mp
->target
, mp
->flags
);
1726 static int pakfire_jail_setup_loopback(struct pakfire_jail
* jail
) {
1727 struct nl_sock
* nl
= NULL
;
1728 struct nl_cache
* cache
= NULL
;
1729 struct rtnl_link
* link
= NULL
;
1730 struct rtnl_link
* change
= NULL
;
1733 DEBUG(jail
->pakfire
, "Setting up loopback...\n");
1735 // Allocate a netlink socket
1736 nl
= nl_socket_alloc();
1738 ERROR(jail
->pakfire
, "Could not allocate a netlink socket: %m\n");
1743 // Connect the socket
1744 r
= nl_connect(nl
, NETLINK_ROUTE
);
1746 ERROR(jail
->pakfire
, "Could not connect netlink socket: %s\n", nl_geterror(r
));
1750 // Allocate the netlink cache
1751 r
= rtnl_link_alloc_cache(nl
, AF_UNSPEC
, &cache
);
1753 ERROR(jail
->pakfire
, "Unable to allocate netlink cache: %s\n", nl_geterror(r
));
1757 // Fetch loopback interface
1758 link
= rtnl_link_get_by_name(cache
, "lo");
1760 ERROR(jail
->pakfire
, "Could not find lo interface. Ignoring.\n");
1765 // Allocate a new link
1766 change
= rtnl_link_alloc();
1768 ERROR(jail
->pakfire
, "Could not allocate change link\n");
1773 // Set the link to UP
1774 rtnl_link_set_flags(change
, IFF_UP
);
1776 // Apply any changes
1777 r
= rtnl_link_change(nl
, link
, change
, 0);
1779 ERROR(jail
->pakfire
, "Unable to activate loopback: %s\n", nl_geterror(r
));
1795 static int pakfire_jail_setup_uid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1796 char path
[PATH_MAX
];
1799 // Skip mapping anything when running on /
1800 if (pakfire_on_root(jail
->pakfire
))
1804 r
= pakfire_string_format(path
, "/proc/%d/uid_map", pid
);
1809 const uid_t uid
= pakfire_uid(jail
->pakfire
);
1812 const struct pakfire_subid
* subuid
= pakfire_subuid(jail
->pakfire
);
1816 /* When running as root, we will map the entire range.
1818 When running as a non-privileged user, we will map the root user inside the jail
1819 to the user's UID outside of the jail, and we will map the rest starting from one.
1824 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1825 "0 %lu %lu\n", subuid
->id
, subuid
->length
);
1827 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1828 "0 %lu 1\n1 %lu %lu\n", uid
, subuid
->id
, subuid
->length
);
1832 ERROR(jail
->pakfire
, "Could not map UIDs: %m\n");
1839 static int pakfire_jail_setup_gid_mapping(struct pakfire_jail
* jail
, pid_t pid
) {
1840 char path
[PATH_MAX
];
1843 // Skip mapping anything when running on /
1844 if (pakfire_on_root(jail
->pakfire
))
1848 const gid_t gid
= pakfire_gid(jail
->pakfire
);
1851 const struct pakfire_subid
* subgid
= pakfire_subgid(jail
->pakfire
);
1856 r
= pakfire_string_format(path
, "/proc/%d/gid_map", pid
);
1862 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1863 "0 %lu %lu\n", subgid
->id
, subgid
->length
);
1865 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0,
1866 "0 %lu 1\n1 %lu %lu\n", gid
, subgid
->id
, subgid
->length
);
1870 ERROR(jail
->pakfire
, "Could not map GIDs: %m\n");
1877 static int pakfire_jail_setgroups(struct pakfire_jail
* jail
, pid_t pid
) {
1878 char path
[PATH_MAX
];
1882 r
= pakfire_string_format(path
, "/proc/%d/setgroups", pid
);
1886 r
= pakfire_file_write(jail
->pakfire
, path
, 0, 0, 0, "deny\n");
1888 CTX_ERROR(jail
->ctx
, "Could not set setgroups to deny: %s\n", strerror(errno
));
1895 static int pakfire_jail_send_signal(struct pakfire_jail
* jail
, int fd
) {
1896 const uint64_t val
= 1;
1899 DEBUG(jail
->pakfire
, "Sending signal...\n");
1901 // Write to the file descriptor
1902 r
= eventfd_write(fd
, val
);
1904 ERROR(jail
->pakfire
, "Could not send signal: %s\n", strerror(errno
));
1908 // Close the file descriptor
1914 static int pakfire_jail_wait_for_signal(struct pakfire_jail
* jail
, int fd
) {
1918 DEBUG(jail
->pakfire
, "Waiting for signal...\n");
1920 r
= eventfd_read(fd
, &val
);
1922 ERROR(jail
->pakfire
, "Error waiting for signal: %s\n", strerror(errno
));
1926 // Close the file descriptor
1933 Performs the initialisation that needs to happen in the parent part
1935 static int pakfire_jail_parent(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1938 // Setup UID mapping
1939 r
= pakfire_jail_setup_uid_mapping(jail
, ctx
->pid
);
1943 // Write "deny" to /proc/PID/setgroups
1944 r
= pakfire_jail_setgroups(jail
, ctx
->pid
);
1948 // Setup GID mapping
1949 r
= pakfire_jail_setup_gid_mapping(jail
, ctx
->pid
);
1953 // Parent has finished initialisation
1954 DEBUG(jail
->pakfire
, "Parent has finished initialization\n");
1956 // Send signal to client
1957 r
= pakfire_jail_send_signal(jail
, ctx
->completed_fd
);
1964 static int pakfire_jail_switch_root(struct pakfire_jail
* jail
, const char* root
) {
1967 // Change to the new root
1970 ERROR(jail
->pakfire
, "chdir(%s) failed: %m\n", root
);
1975 r
= pivot_root(".", ".");
1977 ERROR(jail
->pakfire
, "Failed changing into the new root directory %s: %m\n", root
);
1981 // Umount the old root
1982 r
= umount2(".", MNT_DETACH
);
1984 ERROR(jail
->pakfire
, "Could not umount the old root filesystem: %m\n");
1991 static int pakfire_jail_open_pty(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
1994 // Allocate a new PTY
1995 ctx
->pty
.master
.fd
= posix_openpt(O_RDWR
|O_NONBLOCK
|O_NOCTTY
|O_CLOEXEC
);
1996 if (ctx
->pty
.master
.fd
< 0)
2000 r
= ptsname_r(ctx
->pty
.master
.fd
, ctx
->pty
.console
, sizeof(ctx
->pty
.console
));
2004 CTX_DEBUG(jail
->ctx
, "Allocated console at %s (%d)\n", ctx
->pty
.console
, ctx
->pty
.master
.fd
);
2006 // Unlock the master device
2007 r
= unlockpt(ctx
->pty
.master
.fd
);
2009 CTX_ERROR(jail
->ctx
, "Could not unlock the PTY: %s\n", strerror(errno
));
2014 r
= pakfire_symlink(jail
->ctx
, ctx
->pty
.console
, "/dev/console");
2021 static int pakfire_jail_setup_terminal(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
) {
2025 // Open a new terminal
2026 fd
= open("/dev/console", O_RDWR
|O_NOCTTY
);
2028 CTX_ERROR(jail
->ctx
, "Failed to open a new terminal: %s\n", strerror(errno
));
2032 CTX_DEBUG(jail
->ctx
, "Opened a new terminal %d\n", fd
);
2034 // Connect the new terminal to standard input
2035 r
= dup2(fd
, STDIN_FILENO
);
2037 CTX_ERROR(jail
->ctx
, "Failed to open standard input: %s\n", strerror(errno
));
2041 // Connect the new terminal to standard output
2042 r
= dup2(fd
, STDOUT_FILENO
);
2044 CTX_ERROR(jail
->ctx
, "Failed to open standard output: %s\n", strerror(errno
));
2048 // Connect the new terminal to standard error
2049 r
= dup2(fd
, STDERR_FILENO
);
2051 CTX_ERROR(jail
->ctx
, "Failed to open standard error: %s\n", strerror(errno
));
2058 static int pakfire_jail_child(struct pakfire_jail
* jail
, struct pakfire_jail_exec
* ctx
,
2059 const char* argv
[]) {
2062 // Redirect any logging to our log pipe
2063 pakfire_ctx_set_log_callback(jail
->ctx
, pakfire_jail_log_redirect
, &ctx
->pipes
);
2066 pid_t pid
= getpid();
2068 DEBUG(jail
->pakfire
, "Launched child process in jail with PID %d\n", pid
);
2070 // Wait for the parent to finish initialization
2071 r
= pakfire_jail_wait_for_signal(jail
, ctx
->completed_fd
);
2076 r
= prctl(PR_SET_PDEATHSIG
, SIGKILL
, 0, 0, 0);
2078 ERROR(jail
->pakfire
, "Could not configure to die with parent: %m\n");
2082 // Make this process dumpable
2083 r
= prctl (PR_SET_DUMPABLE
, 1, 0, 0, 0);
2085 ERROR(jail
->pakfire
, "Could not make the process dumpable: %m\n");
2089 // Don't drop any capabilities on setuid()
2090 r
= prctl(PR_SET_KEEPCAPS
, 1);
2092 ERROR(jail
->pakfire
, "Could not set PR_SET_KEEPCAPS: %m\n");
2097 uid_t uid
= getuid();
2098 gid_t gid
= getgid();
2101 uid_t euid
= geteuid();
2102 gid_t egid
= getegid();
2104 DEBUG(jail
->pakfire
, " UID: %u (effective %u)\n", uid
, euid
);
2105 DEBUG(jail
->pakfire
, " GID: %u (effective %u)\n", gid
, egid
);
2107 // Log all mountpoints
2108 pakfire_mount_list(jail
->ctx
);
2110 // Fail if we are not PID 1
2112 CTX_ERROR(jail
->ctx
, "Child process is not PID 1\n");
2116 // Fail if we are not running as root
2117 if (uid
|| gid
|| euid
|| egid
) {
2118 ERROR(jail
->pakfire
, "Child process is not running as root\n");
2122 const int socket_send
= pakfire_jail_get_pipe_to_write(jail
, &ctx
->socket
);
2124 // Mount all default stuff
2125 r
= pakfire_mount_all(jail
->pakfire
, PAKFIRE_MNTNS_INNER
, 0);
2129 const char* root
= pakfire_get_path(jail
->pakfire
);
2130 const char* arch
= pakfire_get_effective_arch(jail
->pakfire
);
2132 // Change mount propagation to slave to receive anything from the parent namespace
2133 r
= pakfire_mount_change_propagation(jail
->ctx
, "/", MS_SLAVE
);
2137 // Make root a mountpoint in the new mount namespace
2138 r
= pakfire_mount_make_mounpoint(jail
->pakfire
, root
);
2142 // Change mount propagation to private
2143 r
= pakfire_mount_change_propagation(jail
->ctx
, root
, MS_PRIVATE
);
2147 // Change root (unless root is /)
2148 if (!pakfire_on_root(jail
->pakfire
)) {
2150 r
= pakfire_jail_mount(jail
, ctx
);
2155 r
= pakfire_jail_switch_root(jail
, root
);
2161 unsigned long persona
= pakfire_arch_personality(arch
);
2163 r
= personality(persona
);
2165 ERROR(jail
->pakfire
, "Could not set personality (%x)\n", (unsigned int)persona
);
2171 if (!pakfire_jail_exec_has_flag(ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
2172 r
= pakfire_jail_setup_loopback(jail
);
2179 DEBUG(jail
->pakfire
, "Setting nice level to %d\n", jail
->nice
);
2181 r
= setpriority(PRIO_PROCESS
, pid
, jail
->nice
);
2183 ERROR(jail
->pakfire
, "Could not set nice level: %m\n");
2188 // Create a new session
2191 CTX_ERROR(jail
->ctx
, "Could not create a new session: %s\n", strerror(errno
));
2195 // Allocate a new PTY
2196 r
= pakfire_jail_open_pty(jail
, ctx
);
2198 CTX_ERROR(jail
->ctx
, "Could not allocate a new PTY: %s\n", strerror(-r
));
2202 // Send the PTY master to the parent process
2203 r
= pakfire_jail_send_fd(jail
, socket_send
, ctx
->pty
.master
.fd
);
2205 CTX_ERROR(jail
->ctx
, "Failed sending the PTY master to the parent: %s\n", strerror(-r
));
2209 // Setup the terminal
2210 r
= pakfire_jail_setup_terminal(jail
, ctx
);
2214 // Close the master of the PTY
2215 close(ctx
->pty
.master
.fd
);
2216 ctx
->pty
.master
.fd
= -1;
2221 // Close other end of log pipes
2222 close(ctx
->pipes
.log_INFO
[0]);
2223 close(ctx
->pipes
.log_ERROR
[0]);
2225 close(ctx
->pipes
.log_DEBUG
[0]);
2226 #endif /* ENABLE_DEBUG */
2228 // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html)
2229 r
= pakfire_rlimit_reset_nofile(jail
->pakfire
);
2234 r
= pakfire_jail_set_capabilities(jail
);
2238 // Show capabilities
2239 r
= pakfire_jail_show_capabilities(jail
);
2244 r
= pakfire_jail_limit_syscalls(jail
);
2248 DEBUG(jail
->pakfire
, "Child process initialization done\n");
2249 DEBUG(jail
->pakfire
, "Launching command:\n");
2252 for (unsigned int i
= 0; argv
[i
]; i
++)
2253 DEBUG(jail
->pakfire
, " argv[%u] = %s\n", i
, argv
[i
]);
2256 r
= execvpe(argv
[0], (char**)argv
, jail
->env
);
2258 // Translate errno into regular exit code
2261 // Ignore if the command doesn't exist
2262 if (ctx
->flags
& PAKFIRE_JAIL_NOENT_OK
)
2273 ERROR(jail
->pakfire
, "Could not execve(%s): %m\n", argv
[0]);
2276 // We should not get here
2280 // Run a command in the jail
2281 static int __pakfire_jail_exec(struct pakfire_jail
* jail
, const char* argv
[],
2282 pakfire_jail_communicate_in communicate_in
,
2283 pakfire_jail_communicate_out communicate_out
,
2284 void* data
, int flags
) {
2288 // Check if argv is valid
2289 if (!argv
|| !argv
[0]) {
2294 // Initialize context for this call
2295 struct pakfire_jail_exec ctx
= {
2298 .socket
= { -1, -1 },
2301 .log_INFO
= { -1, -1 },
2302 .log_ERROR
= { -1, -1 },
2304 .log_DEBUG
= { -1, -1 },
2305 #endif /* ENABLE_DEBUG */
2309 .in
= communicate_in
,
2310 .out
= communicate_out
,
2330 DEBUG(jail
->pakfire
, "Executing jail...\n");
2332 // Enable networking in interactive mode
2333 if (ctx
.flags
& PAKFIRE_JAIL_PTY_FORWARDING
)
2334 ctx
.flags
|= PAKFIRE_JAIL_HAS_NETWORKING
;
2337 Setup a file descriptor which can be used to notify the client that the parent
2338 has completed configuration.
2340 ctx
.completed_fd
= eventfd(0, EFD_CLOEXEC
);
2341 if (ctx
.completed_fd
< 0) {
2342 ERROR(jail
->pakfire
, "eventfd() failed: %m\n");
2346 // Create a UNIX domain socket
2347 r
= socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ctx
.socket
);
2349 CTX_ERROR(jail
->ctx
, "Could not create UNIX socket: %s\n", strerror(errno
));
2354 // Setup pipes for logging
2356 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_INFO
, O_CLOEXEC
);
2361 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_ERROR
, O_CLOEXEC
);
2367 r
= pakfire_jail_setup_pipe(jail
, &ctx
.pipes
.log_DEBUG
, O_CLOEXEC
);
2370 #endif /* ENABLE_DEBUG */
2372 // Configure child process
2373 struct clone_args args
= {
2383 .exit_signal
= SIGCHLD
,
2384 .pidfd
= (long long unsigned int)&ctx
.pidfd
,
2387 // Launch the process in a cgroup that is a leaf of the configured cgroup
2389 args
.flags
|= CLONE_INTO_CGROUP
;
2392 const char* uuid
= pakfire_jail_uuid(jail
);
2394 // Create a temporary cgroup
2395 r
= pakfire_cgroup_child(&ctx
.cgroup
, jail
->cgroup
, uuid
, 0);
2397 ERROR(jail
->pakfire
, "Could not create cgroup for jail: %m\n");
2401 // Clone into this cgroup
2402 args
.cgroup
= pakfire_cgroup_fd(ctx
.cgroup
);
2406 if (!pakfire_jail_exec_has_flag(&ctx
, PAKFIRE_JAIL_HAS_NETWORKING
)) {
2407 args
.flags
|= CLONE_NEWNET
;
2410 // Fork this process
2411 ctx
.pid
= clone3(&args
, sizeof(args
));
2413 ERROR(jail
->pakfire
, "Could not clone: %m\n");
2417 } else if (ctx
.pid
== 0) {
2418 r
= pakfire_jail_child(jail
, &ctx
, argv
);
2423 r
= pakfire_jail_parent(jail
, &ctx
);
2427 DEBUG(jail
->pakfire
, "Waiting for PID %d to finish its work\n", ctx
.pid
);
2429 // Read output of the child process
2430 r
= pakfire_jail_wait(jail
, &ctx
);
2434 // Handle exit status
2435 switch (ctx
.status
.si_code
) {
2437 DEBUG(jail
->pakfire
, "The child process exited with code %d\n",
2438 ctx
.status
.si_status
);
2441 exit
= ctx
.status
.si_status
;
2445 ERROR(jail
->pakfire
, "The child process was killed\n");
2450 ERROR(jail
->pakfire
, "The child process terminated abnormally\n");
2453 // Log anything else
2455 ERROR(jail
->pakfire
, "Unknown child exit code: %d\n", ctx
.status
.si_code
);
2460 // Destroy the temporary cgroup (if any)
2462 // Read cgroup stats
2463 pakfire_cgroup_stat(ctx
.cgroup
, &ctx
.cgroup_stats
);
2464 pakfire_cgroup_stat_dump(ctx
.cgroup
, &ctx
.cgroup_stats
);
2465 pakfire_cgroup_destroy(ctx
.cgroup
);
2466 pakfire_cgroup_unref(ctx
.cgroup
);
2469 // Close any file descriptors
2472 if (ctx
.pty
.master
.fd
>= 0)
2473 close(ctx
.pty
.master
.fd
);
2474 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_INFO
);
2475 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_ERROR
);
2477 pakfire_jail_close_pipe(jail
, ctx
.pipes
.log_DEBUG
);
2478 #endif /* ENABLE_DEBUG */
2479 pakfire_jail_close_pipe(jail
, ctx
.socket
);
2484 PAKFIRE_EXPORT
int pakfire_jail_exec(
2485 struct pakfire_jail
* jail
,
2487 pakfire_jail_communicate_in callback_in
,
2488 pakfire_jail_communicate_out callback_out
,
2489 void* data
, int flags
) {
2490 return __pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, flags
);
2493 static int pakfire_jail_exec_interactive(
2494 struct pakfire_jail
* jail
, const char* argv
[], int flags
) {
2497 flags
|= PAKFIRE_JAIL_PTY_FORWARDING
;
2499 // Setup interactive stuff
2500 r
= pakfire_jail_setup_interactive_env(jail
);
2504 return __pakfire_jail_exec(jail
, argv
, NULL
, NULL
, NULL
, flags
);
2507 int pakfire_jail_exec_script(struct pakfire_jail
* jail
,
2511 pakfire_jail_communicate_in callback_in
,
2512 pakfire_jail_communicate_out callback_out
,
2514 char path
[PATH_MAX
];
2515 const char** argv
= NULL
;
2519 const char* root
= pakfire_get_path(jail
->pakfire
);
2521 // Write the scriptlet to disk
2522 r
= pakfire_path_append(path
, root
, PAKFIRE_TMP_DIR
"/pakfire-script.XXXXXX");
2526 // Create a temporary file
2527 f
= pakfire_mktemp(path
, 0700);
2529 ERROR(jail
->pakfire
, "Could not create temporary file: %m\n");
2533 DEBUG(jail
->pakfire
, "Writing script to %s:\n%.*s\n", path
, (int)size
, script
);
2536 r
= fprintf(f
, "%s", script
);
2538 ERROR(jail
->pakfire
, "Could not write script to file %s: %m\n", path
);
2545 ERROR(jail
->pakfire
, "Could not close script file %s: %m\n", path
);
2551 // Count how many arguments were passed
2552 unsigned int argc
= 1;
2554 for (const char** arg
= args
; *arg
; arg
++)
2558 argv
= calloc(argc
+ 1, sizeof(*argv
));
2560 ERROR(jail
->pakfire
, "Could not allocate argv: %m\n");
2565 argv
[0] = (root
) ? pakfire_path_relpath(root
, path
) : path
;
2568 for (unsigned int i
= 1; i
< argc
; i
++)
2569 argv
[i
] = args
[i
-1];
2572 r
= pakfire_jail_exec(jail
, argv
, callback_in
, callback_out
, data
, 0);
2580 // Remove script from disk
2588 A convenience function that creates a new jail, runs the given command and destroys
2591 int pakfire_jail_run(struct pakfire
* pakfire
, const char* argv
[], int flags
, char** output
) {
2592 struct pakfire_jail
* jail
= NULL
;
2595 // Create a new jail
2596 r
= pakfire_jail_create(&jail
, pakfire
);
2600 // Execute the command
2601 r
= pakfire_jail_exec(jail
, argv
, NULL
, pakfire_jail_capture_stdout
, output
, 0);
2605 pakfire_jail_unref(jail
);
2610 int pakfire_jail_run_script(struct pakfire
* pakfire
,
2611 const char* script
, const size_t length
, const char* argv
[], int flags
) {
2612 struct pakfire_jail
* jail
= NULL
;
2615 // Create a new jail
2616 r
= pakfire_jail_create(&jail
, pakfire
);
2620 // Execute the command
2621 r
= pakfire_jail_exec_script(jail
, script
, length
, argv
, NULL
, NULL
, NULL
);
2625 pakfire_jail_unref(jail
);
2630 int pakfire_jail_shell(struct pakfire_jail
* jail
) {
2633 const char* argv
[] = {
2634 "/bin/bash", "--login", NULL
,
2637 // Execute /bin/bash
2638 r
= pakfire_jail_exec_interactive(jail
, argv
, 0);
2644 // Ignore any return codes from the shell
2648 static int pakfire_jail_run_if_possible(struct pakfire
* pakfire
, const char** argv
) {
2649 char path
[PATH_MAX
];
2652 r
= pakfire_path(pakfire
, path
, "%s", *argv
);
2656 // Check if the file is executable
2657 r
= access(path
, X_OK
);
2659 DEBUG(pakfire
, "%s is not executable. Skipping...\n", *argv
);
2663 return pakfire_jail_run(pakfire
, argv
, 0, NULL
);
2666 int pakfire_jail_ldconfig(struct pakfire
* pakfire
) {
2667 const char* argv
[] = {
2672 return pakfire_jail_run_if_possible(pakfire
, argv
);
2675 int pakfire_jail_run_systemd_tmpfiles(struct pakfire
* pakfire
) {
2676 const char* argv
[] = {
2677 "/usr/bin/systemd-tmpfiles",
2682 return pakfire_jail_run_if_possible(pakfire
, argv
);