Compare commits
10 Commits
3f917b326b
...
1247f5d3e5
Author | SHA1 | Date | |
---|---|---|---|
1247f5d3e5 | |||
![]() |
765eb0bf16 | ||
![]() |
0608ec42f2 | ||
![]() |
c9b2413465 | ||
![]() |
ba23b05545 | ||
![]() |
57d8aa8ffe | ||
![]() |
cbca08cd38 | ||
![]() |
fcfb592adc | ||
![]() |
d02bb6ca05 | ||
![]() |
45b8632dcc |
23
conf.c
23
conf.c
@@ -38,6 +38,7 @@
|
|||||||
#include "ip.h"
|
#include "ip.h"
|
||||||
#include "passt.h"
|
#include "passt.h"
|
||||||
#include "netlink.h"
|
#include "netlink.h"
|
||||||
|
#include "tap.h"
|
||||||
#include "udp.h"
|
#include "udp.h"
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
#include "pasta.h"
|
#include "pasta.h"
|
||||||
@@ -1093,7 +1094,7 @@ static void conf_ugid(char *runas, uid_t *uid, gid_t *gid)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* ...otherwise use nobody:nobody */
|
/* ...otherwise use nobody:nobody */
|
||||||
warn("Don't run as root. Changing to nobody...");
|
warn("Started as root, will change to nobody.");
|
||||||
{
|
{
|
||||||
#ifndef GLIBC_NO_STATIC_NSS
|
#ifndef GLIBC_NO_STATIC_NSS
|
||||||
const struct passwd *pw;
|
const struct passwd *pw;
|
||||||
@@ -1113,6 +1114,18 @@ static void conf_ugid(char *runas, uid_t *uid, gid_t *gid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* conf_open_files() - Open files as requested by configuration
|
||||||
|
* @c: Execution context
|
||||||
|
*/
|
||||||
|
static void conf_open_files(struct ctx *c)
|
||||||
|
{
|
||||||
|
if (c->mode == MODE_PASST && c->fd_tap == -1)
|
||||||
|
c->fd_tap_listen = tap_sock_unix_open(c->sock_path);
|
||||||
|
|
||||||
|
c->pidfile_fd = pidfile_open(c->pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* conf() - Process command-line arguments and set configuration
|
* conf() - Process command-line arguments and set configuration
|
||||||
* @c: Execution context
|
* @c: Execution context
|
||||||
@@ -1443,12 +1456,12 @@ void conf(struct ctx *c, int argc, char **argv)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
if (*c->pid_file)
|
if (*c->pidfile)
|
||||||
die("Multiple --pid options given");
|
die("Multiple --pid options given");
|
||||||
|
|
||||||
ret = snprintf(c->pid_file, sizeof(c->pid_file), "%s",
|
ret = snprintf(c->pidfile, sizeof(c->pidfile), "%s",
|
||||||
optarg);
|
optarg);
|
||||||
if (ret <= 0 || ret >= (int)sizeof(c->pid_file))
|
if (ret <= 0 || ret >= (int)sizeof(c->pidfile))
|
||||||
die("Invalid PID file: %s", optarg);
|
die("Invalid PID file: %s", optarg);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1712,6 +1725,8 @@ void conf(struct ctx *c, int argc, char **argv)
|
|||||||
else if (optind != argc)
|
else if (optind != argc)
|
||||||
die("Extra non-option argument: %s", argv[optind]);
|
die("Extra non-option argument: %s", argv[optind]);
|
||||||
|
|
||||||
|
conf_open_files(c); /* Before any possible setuid() / setgid() */
|
||||||
|
|
||||||
isolate_user(uid, gid, !netns_only, userns, c->mode);
|
isolate_user(uid, gid, !netns_only, userns, c->mode);
|
||||||
|
|
||||||
if (c->pasta_conf_ns)
|
if (c->pasta_conf_ns)
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
@{PROC}/@{pid}/net/udp r,
|
@{PROC}/@{pid}/net/udp r,
|
||||||
@{PROC}/@{pid}/net/udp6 r,
|
@{PROC}/@{pid}/net/udp6 r,
|
||||||
|
|
||||||
@{run}/user/@{uid}/** rw, # pasta_open_ns(), main()
|
@{run}/user/@{uid}/** rw, # pasta_open_ns()
|
||||||
|
|
||||||
@{PROC}/[0-9]*/ns/ r, # pasta_netns_quit_init(),
|
@{PROC}/[0-9]*/ns/ r, # pasta_netns_quit_init(),
|
||||||
@{PROC}/[0-9]*/ns/net r, # pasta_wait_for_ns(),
|
@{PROC}/[0-9]*/ns/net r, # pasta_wait_for_ns(),
|
||||||
|
@@ -19,9 +19,12 @@ profile passt /usr/bin/passt{,.avx2} {
|
|||||||
include <abstractions/passt>
|
include <abstractions/passt>
|
||||||
|
|
||||||
# Alternatively: include <abstractions/user-tmp>
|
# Alternatively: include <abstractions/user-tmp>
|
||||||
owner /tmp/** w, # tap_sock_unix_init(), pcap(),
|
owner /tmp/** w, # tap_sock_unix_open(),
|
||||||
# write_pidfile(),
|
# tap_sock_unix_init(), pcap(),
|
||||||
|
# pidfile_open(),
|
||||||
|
# pidfile_write(),
|
||||||
# logfile_init()
|
# logfile_init()
|
||||||
|
|
||||||
owner @{HOME}/** w, # pcap(), write_pidfile()
|
owner @{HOME}/** w, # pcap(), pidfile_open(),
|
||||||
|
# pidfile_write()
|
||||||
}
|
}
|
||||||
|
@@ -19,10 +19,13 @@ profile pasta /usr/bin/pasta{,.avx2} flags=(attach_disconnected) {
|
|||||||
include <abstractions/pasta>
|
include <abstractions/pasta>
|
||||||
|
|
||||||
# Alternatively: include <abstractions/user-tmp>
|
# Alternatively: include <abstractions/user-tmp>
|
||||||
/tmp/** rw, # tap_sock_unix_init(), pcap(),
|
/tmp/** rw, # tap_sock_unix_open(),
|
||||||
# write_pidfile(),
|
# tap_sock_unix_init(), pcap(),
|
||||||
|
# pidfile_open(),
|
||||||
|
# pidfile_write(),
|
||||||
# logfile_init(),
|
# logfile_init(),
|
||||||
# pasta_open_ns()
|
# pasta_open_ns()
|
||||||
|
|
||||||
owner @{HOME}/** w, # pcap(), write_pidfile()
|
owner @{HOME}/** w, # pcap(), pidfile_open(),
|
||||||
|
# pidfile_write()
|
||||||
}
|
}
|
||||||
|
17
passt.c
17
passt.c
@@ -199,9 +199,9 @@ void exit_handler(int signal)
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int nfds, i, devnull_fd = -1, pidfile_fd = -1;
|
|
||||||
struct epoll_event events[EPOLL_EVENTS];
|
struct epoll_event events[EPOLL_EVENTS];
|
||||||
char *log_name, argv0[PATH_MAX], *name;
|
char *log_name, argv0[PATH_MAX], *name;
|
||||||
|
int nfds, i, devnull_fd = -1;
|
||||||
struct ctx c = { 0 };
|
struct ctx c = { 0 };
|
||||||
struct rlimit limit;
|
struct rlimit limit;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
@@ -211,7 +211,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
isolate_initial();
|
isolate_initial();
|
||||||
|
|
||||||
c.pasta_netns_fd = c.fd_tap = c.fd_tap_listen = -1;
|
c.pasta_netns_fd = c.fd_tap = c.pidfile_fd = -1;
|
||||||
|
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
@@ -299,15 +299,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*c.pid_file) {
|
|
||||||
if ((pidfile_fd = open(c.pid_file,
|
|
||||||
O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
|
|
||||||
S_IRUSR | S_IWUSR)) < 0) {
|
|
||||||
perror("PID file open");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isolate_prefork(&c))
|
if (isolate_prefork(&c))
|
||||||
die("Failed to sandbox process, exiting");
|
die("Failed to sandbox process, exiting");
|
||||||
|
|
||||||
@@ -315,9 +306,9 @@ int main(int argc, char **argv)
|
|||||||
__openlog(log_name, 0, LOG_DAEMON);
|
__openlog(log_name, 0, LOG_DAEMON);
|
||||||
|
|
||||||
if (!c.foreground)
|
if (!c.foreground)
|
||||||
__daemon(pidfile_fd, devnull_fd);
|
__daemon(c.pidfile_fd, devnull_fd);
|
||||||
else
|
else
|
||||||
write_pidfile(pidfile_fd, getpid());
|
pidfile_write(c.pidfile_fd, getpid());
|
||||||
|
|
||||||
if (pasta_child_pid)
|
if (pasta_child_pid)
|
||||||
kill(pasta_child_pid, SIGUSR1);
|
kill(pasta_child_pid, SIGUSR1);
|
||||||
|
8
passt.h
8
passt.h
@@ -184,7 +184,8 @@ struct ip6_ctx {
|
|||||||
* @nofile: Maximum number of open files (ulimit -n)
|
* @nofile: Maximum number of open files (ulimit -n)
|
||||||
* @sock_path: Path for UNIX domain socket
|
* @sock_path: Path for UNIX domain socket
|
||||||
* @pcap: Path for packet capture file
|
* @pcap: Path for packet capture file
|
||||||
* @pid_file: Path to PID file, empty string if not configured
|
* @pidfile: Path to PID file, empty string if not configured
|
||||||
|
* @pidfile_fd: File descriptor for PID file, -1 if none
|
||||||
* @pasta_netns_fd: File descriptor for network namespace in pasta mode
|
* @pasta_netns_fd: File descriptor for network namespace in pasta mode
|
||||||
* @no_netns_quit: In pasta mode, don't exit if fs-bound namespace is gone
|
* @no_netns_quit: In pasta mode, don't exit if fs-bound namespace is gone
|
||||||
* @netns_base: Base name for fs-bound namespace, if any, in pasta mode
|
* @netns_base: Base name for fs-bound namespace, if any, in pasta mode
|
||||||
@@ -234,7 +235,10 @@ struct ctx {
|
|||||||
int nofile;
|
int nofile;
|
||||||
char sock_path[UNIX_PATH_MAX];
|
char sock_path[UNIX_PATH_MAX];
|
||||||
char pcap[PATH_MAX];
|
char pcap[PATH_MAX];
|
||||||
char pid_file[PATH_MAX];
|
|
||||||
|
char pidfile[PATH_MAX];
|
||||||
|
int pidfile_fd;
|
||||||
|
|
||||||
int one_off;
|
int one_off;
|
||||||
|
|
||||||
int pasta_netns_fd;
|
int pasta_netns_fd;
|
||||||
|
55
tap.c
55
tap.c
@@ -1095,14 +1095,14 @@ restart:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tap_sock_unix_init() - Create and bind AF_UNIX socket, listen for connection
|
* tap_sock_unix_open() - Create and bind AF_UNIX socket
|
||||||
* @c: Execution context
|
* @sock_path: Socket path. If empty, set on return (UNIX_SOCK_PATH as prefix)
|
||||||
|
*
|
||||||
|
* Return: socket descriptor on success, won't return on failure
|
||||||
*/
|
*/
|
||||||
static void tap_sock_unix_init(struct ctx *c)
|
int tap_sock_unix_open(char *sock_path)
|
||||||
{
|
{
|
||||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
union epoll_ref ref = { .type = EPOLL_TYPE_TAP_LISTEN };
|
|
||||||
struct epoll_event ev = { 0 };
|
|
||||||
struct sockaddr_un addr = {
|
struct sockaddr_un addr = {
|
||||||
.sun_family = AF_UNIX,
|
.sun_family = AF_UNIX,
|
||||||
};
|
};
|
||||||
@@ -1111,18 +1111,12 @@ static void tap_sock_unix_init(struct ctx *c)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
die("UNIX socket: %s", strerror(errno));
|
die("UNIX socket: %s", strerror(errno));
|
||||||
|
|
||||||
/* In passt mode, we don't know the guest's MAC until it sends
|
|
||||||
* us packets. Use the broadcast address so our first packets
|
|
||||||
* will reach it.
|
|
||||||
*/
|
|
||||||
memset(&c->mac_guest, 0xff, sizeof(c->mac_guest));
|
|
||||||
|
|
||||||
for (i = 1; i < UNIX_SOCK_MAX; i++) {
|
for (i = 1; i < UNIX_SOCK_MAX; i++) {
|
||||||
char *path = addr.sun_path;
|
char *path = addr.sun_path;
|
||||||
int ex, ret;
|
int ex, ret;
|
||||||
|
|
||||||
if (*c->sock_path)
|
if (*sock_path)
|
||||||
memcpy(path, c->sock_path, UNIX_PATH_MAX);
|
memcpy(path, sock_path, UNIX_PATH_MAX);
|
||||||
else
|
else
|
||||||
snprintf(path, UNIX_PATH_MAX - 1, UNIX_SOCK_PATH, i);
|
snprintf(path, UNIX_PATH_MAX - 1, UNIX_SOCK_PATH, i);
|
||||||
|
|
||||||
@@ -1133,7 +1127,7 @@ static void tap_sock_unix_init(struct ctx *c)
|
|||||||
ret = connect(ex, (const struct sockaddr *)&addr, sizeof(addr));
|
ret = connect(ex, (const struct sockaddr *)&addr, sizeof(addr));
|
||||||
if (!ret || (errno != ENOENT && errno != ECONNREFUSED &&
|
if (!ret || (errno != ENOENT && errno != ECONNREFUSED &&
|
||||||
errno != EACCES)) {
|
errno != EACCES)) {
|
||||||
if (*c->sock_path)
|
if (*sock_path)
|
||||||
die("Socket path %s already in use", path);
|
die("Socket path %s already in use", path);
|
||||||
|
|
||||||
close(ex);
|
close(ex);
|
||||||
@@ -1143,25 +1137,39 @@ static void tap_sock_unix_init(struct ctx *c)
|
|||||||
|
|
||||||
unlink(path);
|
unlink(path);
|
||||||
if (!bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) ||
|
if (!bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) ||
|
||||||
*c->sock_path)
|
*sock_path)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == UNIX_SOCK_MAX)
|
if (i == UNIX_SOCK_MAX)
|
||||||
die("UNIX socket bind: %s", strerror(errno));
|
die("UNIX socket bind: %s", strerror(errno));
|
||||||
|
|
||||||
info("UNIX domain socket bound at %s\n", addr.sun_path);
|
info("UNIX domain socket bound at %s", addr.sun_path);
|
||||||
|
if (!*sock_path)
|
||||||
|
memcpy(sock_path, addr.sun_path, UNIX_PATH_MAX);
|
||||||
|
|
||||||
listen(fd, 0);
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
ref.fd = c->fd_tap_listen = fd;
|
/**
|
||||||
|
* tap_sock_unix_init() - Start listening for connections on AF_UNIX socket
|
||||||
|
* @c: Execution context
|
||||||
|
*/
|
||||||
|
static void tap_sock_unix_init(struct ctx *c)
|
||||||
|
{
|
||||||
|
union epoll_ref ref = { .type = EPOLL_TYPE_TAP_LISTEN };
|
||||||
|
struct epoll_event ev = { 0 };
|
||||||
|
|
||||||
|
listen(c->fd_tap_listen, 0);
|
||||||
|
|
||||||
|
ref.fd = c->fd_tap_listen;
|
||||||
ev.events = EPOLLIN | EPOLLET;
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
ev.data.u64 = ref.u64;
|
ev.data.u64 = ref.u64;
|
||||||
epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap_listen, &ev);
|
epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap_listen, &ev);
|
||||||
|
|
||||||
info("You can now start qemu (>= 7.2, with commit 13c6be96618c):");
|
info("\nYou can now start qemu (>= 7.2, with commit 13c6be96618c):");
|
||||||
info(" kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=%s",
|
info(" kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=%s",
|
||||||
addr.sun_path);
|
c->sock_path);
|
||||||
info("or qrap, for earlier qemu versions:");
|
info("or qrap, for earlier qemu versions:");
|
||||||
info(" ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio");
|
info(" ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio");
|
||||||
}
|
}
|
||||||
@@ -1310,8 +1318,13 @@ void tap_sock_init(struct ctx *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (c->mode == MODE_PASST) {
|
if (c->mode == MODE_PASST) {
|
||||||
if (c->fd_tap_listen == -1)
|
|
||||||
tap_sock_unix_init(c);
|
tap_sock_unix_init(c);
|
||||||
|
|
||||||
|
/* In passt mode, we don't know the guest's MAC address until it
|
||||||
|
* sends us packets. Use the broadcast address so that our
|
||||||
|
* first packets will reach it.
|
||||||
|
*/
|
||||||
|
memset(&c->mac_guest, 0xff, sizeof(c->mac_guest));
|
||||||
} else {
|
} else {
|
||||||
tap_sock_tun_init(c);
|
tap_sock_tun_init(c);
|
||||||
}
|
}
|
||||||
|
1
tap.h
1
tap.h
@@ -68,6 +68,7 @@ void tap_handler_pasta(struct ctx *c, uint32_t events,
|
|||||||
const struct timespec *now);
|
const struct timespec *now);
|
||||||
void tap_handler_passt(struct ctx *c, uint32_t events,
|
void tap_handler_passt(struct ctx *c, uint32_t events,
|
||||||
const struct timespec *now);
|
const struct timespec *now);
|
||||||
|
int tap_sock_unix_open(char *sock_path);
|
||||||
void tap_sock_init(struct ctx *c);
|
void tap_sock_init(struct ctx *c);
|
||||||
|
|
||||||
#endif /* TAP_H */
|
#endif /* TAP_H */
|
||||||
|
28
util.c
28
util.c
@@ -380,11 +380,11 @@ int open_in_ns(const struct ctx *c, const char *path, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pid_file() - Write PID to file, if requested to do so, and close it
|
* pidfile_write() - Write PID to file, if requested to do so, and close it
|
||||||
* @fd: Open PID file descriptor, closed on exit, -1 to skip writing it
|
* @fd: Open PID file descriptor, closed on exit, -1 to skip writing it
|
||||||
* @pid: PID value to write
|
* @pid: PID value to write
|
||||||
*/
|
*/
|
||||||
void write_pidfile(int fd, pid_t pid)
|
void pidfile_write(int fd, pid_t pid)
|
||||||
{
|
{
|
||||||
char pid_buf[12];
|
char pid_buf[12];
|
||||||
int n;
|
int n;
|
||||||
@@ -402,6 +402,28 @@ void write_pidfile(int fd, pid_t pid)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pidfile_open() - Open PID file if needed
|
||||||
|
* @path: Path for PID file, empty string if no PID file is requested
|
||||||
|
*
|
||||||
|
* Return: descriptor for PID file, -1 if path is NULL, won't return on failure
|
||||||
|
*/
|
||||||
|
int pidfile_open(const char *path)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (!*path)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((fd = open(path, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
|
||||||
|
S_IRUSR | S_IWUSR)) < 0) {
|
||||||
|
perror("PID file open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __daemon() - daemon()-like function writing PID file before parent exits
|
* __daemon() - daemon()-like function writing PID file before parent exits
|
||||||
* @pidfile_fd: Open PID file descriptor
|
* @pidfile_fd: Open PID file descriptor
|
||||||
@@ -419,7 +441,7 @@ int __daemon(int pidfile_fd, int devnull_fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pid) {
|
if (pid) {
|
||||||
write_pidfile(pidfile_fd, pid);
|
pidfile_write(pidfile_fd, pid);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
util.h
4
util.h
@@ -6,6 +6,7 @@
|
|||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -156,7 +157,8 @@ char *line_read(char *buf, size_t len, int fd);
|
|||||||
void ns_enter(const struct ctx *c);
|
void ns_enter(const struct ctx *c);
|
||||||
bool ns_is_init(void);
|
bool ns_is_init(void);
|
||||||
int open_in_ns(const struct ctx *c, const char *path, int flags);
|
int open_in_ns(const struct ctx *c, const char *path, int flags);
|
||||||
void write_pidfile(int fd, pid_t pid);
|
int pidfile_open(const char *path);
|
||||||
|
void pidfile_write(int fd, pid_t pid);
|
||||||
int __daemon(int pidfile_fd, int devnull_fd);
|
int __daemon(int pidfile_fd, int devnull_fd);
|
||||||
int fls(unsigned long x);
|
int fls(unsigned long x);
|
||||||
int write_file(const char *path, const char *buf);
|
int write_file(const char *path, const char *buf);
|
||||||
|
Reference in New Issue
Block a user