out:
return ret;
}
+
+int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path)
+{
+ size_t len;
+
+ len = strlen(path);
+ if (len == 0)
+ return minus_one_set_errno(EINVAL);
+ if (path[0] != '/' && path[0] != '@')
+ return minus_one_set_errno(EINVAL);
+ if (path[1] == '\0')
+ return minus_one_set_errno(EINVAL);
+
+ if (len + 1 > sizeof(ret->sun_path))
+ return minus_one_set_errno(EINVAL);
+
+ *ret = (struct sockaddr_un){
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ memcpy(ret->sun_path + 1, path + 1, len);
+ return (int)(offsetof(struct sockaddr_un, sun_path) + len);
+ }
+
+ memcpy(ret->sun_path, path, len + 1);
+ return (int)(offsetof(struct sockaddr_un, sun_path) + len + 1);
+}
+
+int lxc_unix_connect(struct sockaddr_un *addr)
+{
+ __do_close_prot_errno int fd = -EBADF;
+ int ret;
+ ssize_t len;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, SOCK_CLOEXEC);
+ if (fd < 0)
+ return -1;
+
+ if (addr->sun_path[0] == '\0')
+ len = strlen(&addr->sun_path[1]);
+ else
+ len = strlen(&addr->sun_path[0]);
+ ret = connect(fd, (struct sockaddr *)&addr,
+ offsetof(struct sockaddr_un, sun_path) + len + 1);
+ if (ret < 0)
+ return -1;
+
+ return move_fd(fd);
+}
+
+int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout)
+{
+ struct timeval out = {0};
+ int ret;
+
+ out.tv_sec = snd_timeout;
+ ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&out,
+ sizeof(out));
+ if (ret < 0)
+ return -1;
+
+ out.tv_sec = rcv_timeout;
+ ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&out,
+ sizeof(out));
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
#define __LXC_AF_UNIX_H
#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
/* does not enforce \0-termination */
extern int lxc_abstract_unix_open(const char *path, int type, int flags);
void *data, size_t size);
extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size);
extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size);
+extern int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path);
+extern int lxc_unix_connect(struct sockaddr_un *addr);
+extern int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout);
#endif /* __LXC_AF_UNIX_H */
new->has_seccomp_notify = false;
new->seccomp_notify_fd = -EBADF;
new->seccomp_notify_proxy_fd = -EBADF;
+ memset(&new->seccomp_notify_proxy_addr, 0, sizeof(new->seccomp_notify_proxy_addr));
new->seccomp_notify_req = NULL;
new->seccomp_notify_resp = NULL;
#endif
bool has_seccomp_notify;
int seccomp_notify_fd;
int seccomp_notify_proxy_fd;
+ struct sockaddr_un seccomp_notify_proxy_addr;
struct seccomp_notif *seccomp_notify_req;
struct seccomp_notif_resp *seccomp_notify_resp;
#endif
#include <time.h>
#include <unistd.h>
+#include "af_unix.h"
#include "conf.h"
#include "config.h"
#include "confile.h"
lxc_config_define(rootfs_path);
lxc_config_define(seccomp_profile);
lxc_config_define(seccomp_allow_nesting);
+lxc_config_define(seccomp_notify_proxy);
lxc_config_define(selinux_context);
lxc_config_define(signal_halt);
lxc_config_define(signal_reboot);
{ "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
{ "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, },
{ "lxc.seccomp.allow_nesting", set_config_seccomp_allow_nesting, get_config_seccomp_allow_nesting, clr_config_seccomp_allow_nesting, },
+ { "lxc.seccomp.notify.proxy", set_config_seccomp_notify_proxy, get_config_seccomp_notify_proxy, clr_config_seccomp_notify_proxy, },
{ "lxc.seccomp.profile", set_config_seccomp_profile, get_config_seccomp_profile, clr_config_seccomp_profile, },
{ "lxc.selinux.context", set_config_selinux_context, get_config_selinux_context, clr_config_selinux_context, },
{ "lxc.signal.halt", set_config_signal_halt, get_config_signal_halt, clr_config_signal_halt, },
return -1;
if (lxc_conf->seccomp_allow_nesting > 1)
+ return minus_one_set_errno(EINVAL);
+
+ return 0;
+}
+
+static int set_config_seccomp_notify_proxy(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ const char *offset;
+
+ if (lxc_config_value_empty(value))
+ return clr_config_seccomp_notify_proxy(key, lxc_conf, NULL);
+
+ if (strncmp(value, "unix:", 5) != 0)
+ return minus_one_set_errno(EINVAL);
+
+ offset = value + 5;
+ if (lxc_unix_sockaddr(&lxc_conf->seccomp_notify_proxy_addr, offset) < 0)
return -1;
return 0;
+#else
+ return minus_one_set_errno(ENOSYS);
+#endif
}
static int set_config_seccomp_profile(const char *key, const char *value,
return lxc_get_conf_int(c, retv, inlen, c->seccomp_allow_nesting);
}
+static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ return lxc_get_conf_str(retv, inlen,
+ (c->seccomp_notify_proxy_addr.sun_path[0]) == '/'
+ ? &c->seccomp_notify_proxy_addr.sun_path[0]
+ : &c->seccomp_notify_proxy_addr.sun_path[1]);
+#else
+ return minus_one_set_errno(ENOSYS);
+#endif
+}
+
static int get_config_seccomp_profile(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
return 0;
}
+static inline int clr_config_seccomp_notify_proxy(const char *key,
+ struct lxc_conf *c, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ memset(&c->seccomp_notify_proxy_addr, 0,
+ sizeof(c->seccomp_notify_proxy_addr));
+ return 0;
+#else
+ return minus_one_set_errno(ENOSYS);
+#endif
+}
+
static inline int clr_config_seccomp_profile(const char *key,
struct lxc_conf *c, void *data)
{
#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
if (handler->conf->has_seccomp_notify &&
- handler->conf->seccomp_notify_proxy_fd >= 0) {
+ handler->conf->seccomp_notify_proxy_addr.sun_path[1] != '\0') {
+ __do_close_prot_errno int notify_fd = -EBADF;
+
+ notify_fd = lxc_unix_connect(&handler->conf->seccomp_notify_proxy_addr);
+ if (notify_fd < 0)
+ goto out_mainloop_console;
+
+ /* 30 second timeout */
+ ret = lxc_socket_set_timeout(notify_fd, 30, 30);
+ if (ret)
+ goto out_mainloop_console;
+
ret = lxc_mainloop_add_handler(&descr,
handler->conf->seccomp_notify_fd,
seccomp_notify_handler, handler);
handler->conf->seccomp_notify_fd);
goto out_mainloop_console;
}
+
+ handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
}
#endif