Unverified Commit 78af4d9c by Stéphane Graber Committed by GitHub

Merge pull request #3825 from brauner/2021-05-04.fixes

lxc.arch fixes
parents 13723cb9 3a881819
......@@ -48,10 +48,6 @@
#include "terminal.h"
#include "utils.h"
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
lxc_log_define(attach, lxc);
/* Define default options if no options are supplied by the user. */
......@@ -99,7 +95,7 @@ struct attach_context {
uid_t target_host_gid;
char *lsm_label;
struct lxc_container *container;
signed long personality;
personality_t personality;
unsigned long long capability_mask;
int ns_inherited;
int ns_fd[LXC_NS_MAX];
......@@ -201,9 +197,10 @@ static struct attach_context *alloc_attach_context(void)
}
static int get_personality(const char *name, const char *lxcpath,
signed long *personality)
personality_t *personality)
{
__do_free char *p = NULL;
int ret;
signed long per;
p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath);
......@@ -212,9 +209,9 @@ static int get_personality(const char *name, const char *lxcpath,
return 0;
}
per = lxc_config_parse_arch(p);
if (per == LXC_ARCH_UNCHANGED)
return ret_errno(EINVAL);
ret = lxc_config_parse_arch(p, &per);
if (ret < 0)
return syserror("Failed to parse personality");
*personality = per;
return 0;
......@@ -1147,24 +1144,22 @@ __noreturn static void do_attach(struct attach_payload *ap)
}
/* Now perform additional attachments. */
#if HAVE_SYS_PERSONALITY_H
if (options->attach_flags & LXC_ATTACH_SET_PERSONALITY) {
long new_personality;
if (options->personality < 0)
if (options->personality == LXC_ATTACH_DETECT_PERSONALITY)
new_personality = ctx->personality;
else
new_personality = options->personality;
if (new_personality != LXC_ARCH_UNCHANGED) {
ret = personality(new_personality);
ret = lxc_personality(new_personality);
if (ret < 0)
goto on_error;
TRACE("Set new personality");
}
}
#endif
if (options->attach_flags & LXC_ATTACH_DROP_CAPABILITIES) {
ret = drop_capabilities(ctx);
......
......@@ -82,6 +82,8 @@ typedef struct lxc_groups_t {
gid_t *list;
} lxc_groups_t;
#define LXC_ATTACH_DETECT_PERSONALITY ~0L
/*!
* LXC attach options for \ref lxc_container \c attach().
*/
......@@ -92,7 +94,7 @@ typedef struct lxc_attach_options_t {
/*! The namespaces to attach to (CLONE_NEW... flags) */
int namespaces;
/*! Initial personality (\c -1 to autodetect).
/*! Initial personality (\c LXC_ATTACH_DETECT_PERSONALITY to autodetect).
* \warning This may be ignored if lxc is compiled without personality
* support)
*/
......@@ -156,23 +158,23 @@ typedef struct lxc_attach_options_t {
} lxc_attach_options_t;
/*! Default attach options to use */
#define LXC_ATTACH_OPTIONS_DEFAULT \
{ \
.attach_flags = LXC_ATTACH_DEFAULT, \
.namespaces = -1, \
.personality = 0xffffffff, \
.initial_cwd = NULL, \
.uid = (uid_t)-1, \
.gid = (gid_t)-1, \
.env_policy = LXC_ATTACH_KEEP_ENV, \
.extra_env_vars = NULL, \
.extra_keep_env = NULL, \
.stdin_fd = 0, \
.stdout_fd = 1, \
.stderr_fd = 2, \
.log_fd = -EBADF, \
.lsm_label = NULL, \
.groups = {}, \
#define LXC_ATTACH_OPTIONS_DEFAULT \
{ \
.attach_flags = LXC_ATTACH_DEFAULT, \
.namespaces = -1, \
.personality = LXC_ATTACH_DETECT_PERSONALITY, \
.initial_cwd = NULL, \
.uid = (uid_t)-1, \
.gid = (gid_t)-1, \
.env_policy = LXC_ATTACH_KEEP_ENV, \
.extra_env_vars = NULL, \
.extra_keep_env = NULL, \
.stdin_fd = 0, \
.stdout_fd = 1, \
.stderr_fd = 2, \
.log_fd = -EBADF, \
.lsm_label = NULL, \
.groups = {}, \
}
/*!
......
......@@ -126,7 +126,7 @@ static ssize_t lxc_cmd_rsp_recv_fds(int fd_sock, struct unix_fds *fds,
ret = lxc_abstract_unix_recv_fds(fd_sock, fds, rsp, sizeof(*rsp));
if (ret < 0)
return ret;
return log_error(ret, "Failed to receive file descriptors");
/*
* If we end up here with fewer or more file descriptors the caller
......@@ -135,18 +135,18 @@ static ssize_t lxc_cmd_rsp_recv_fds(int fd_sock, struct unix_fds *fds,
*/
if (fds->flags & UNIX_FDS_RECEIVED_EXACT)
return log_info(ret, "Received exact number of file descriptors %u == %u",
fds->fd_count_max, fds->fd_count_ret);
return log_debug(ret, "Received exact number of file descriptors %u == %u",
fds->fd_count_max, fds->fd_count_ret);
if (fds->flags & UNIX_FDS_RECEIVED_LESS)
return log_info(ret, "Received less file descriptors %u < %u",
fds->fd_count_ret, fds->fd_count_max);
return log_debug(ret, "Received less file descriptors %u < %u",
fds->fd_count_ret, fds->fd_count_max);
if (fds->flags & UNIX_FDS_RECEIVED_MORE)
return log_info(ret, "Received more file descriptors (excessive fds were automatically closed) %u > %u",
fds->fd_count_ret, fds->fd_count_max);
return log_debug(ret, "Received more file descriptors (excessive fds were automatically closed) %u > %u",
fds->fd_count_ret, fds->fd_count_max);
INFO("Command \"%s\" received response", cur_cmdstr);
DEBUG("Command \"%s\" received response", cur_cmdstr);
return ret;
}
......
......@@ -80,10 +80,6 @@
#include <sys/capability.h>
#endif
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
#ifndef HAVE_STRLCAT
#include "include/strlcat.h"
#endif
......@@ -1732,21 +1728,18 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
return 0;
}
static int setup_personality(int persona)
static int setup_personality(personality_t persona)
{
int ret;
#if HAVE_SYS_PERSONALITY_H
if (persona == -1)
return 0;
if (persona == LXC_ARCH_UNCHANGED)
return log_debug(0, "Retaining original personality");
ret = personality(persona);
ret = lxc_personality(persona);
if (ret < 0)
return log_error_errno(-1, errno, "Failed to set personality to \"0x%x\"", persona);
INFO("Set personality to \"0x%x\"", persona);
#endif
return syserror("Failed to set personality to \"0lx%lx\"", persona);
INFO("Set personality to \"0lx%lx\"", persona);
return 0;
}
......@@ -2806,7 +2799,7 @@ struct lxc_conf *lxc_conf_init(void)
return NULL;
new->loglevel = LXC_LOG_LEVEL_NOTSET;
new->personality = -1;
new->personality = LXC_ARCH_UNCHANGED;
new->autodev = 1;
new->console.buffer_size = 0;
new->console.log_path = NULL;
......@@ -3737,7 +3730,7 @@ int lxc_setup(struct lxc_handler *handler)
ret = setup_personality(lxc_conf->personality);
if (ret < 0)
return log_error(-1, "Failed to set personality");
return syserror("Failed to set personality");
/* Set sysctl value to a path under /proc/sys as determined from the
* key. For e.g. net.ipv4.ip_forward translated to
......
......@@ -26,6 +26,7 @@
#include "start.h"
#include "storage/storage.h"
#include "string_utils.h"
#include "syscall_wrappers.h"
#include "terminal.h"
#if HAVE_SYS_RESOURCE_H
......@@ -36,6 +37,8 @@
typedef void * scmp_filter_ctx;
#endif
typedef signed long personality_t;
/* worth moving to configure.ac? */
#define subuidfile "/etc/subuid"
#define subgidfile "/etc/subgid"
......@@ -327,7 +330,7 @@ struct lxc_conf {
const char *name;
bool is_execute;
int reboot;
signed long personality;
personality_t personality;
struct utsname *utsname;
struct {
......@@ -628,4 +631,12 @@ static inline void lxc_clear_cgroup2_devices(struct bpf_devices *bpf_devices)
lxc_list_init(&bpf_devices->device_item);
}
static inline int lxc_personality(personality_t persona)
{
if (persona < 0)
return ret_errno(EINVAL);
return personality(persona);
}
#endif /* __LXC_CONF_H */
......@@ -39,10 +39,6 @@
#include "storage/storage.h"
#include "utils.h"
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
#endif
......@@ -1392,14 +1388,14 @@ static int set_config_hooks_version(const char *key, const char *value,
static int set_config_personality(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
signed long personality;
int ret;
personality_t personality;
personality = lxc_config_parse_arch(value);
if (personality >= 0)
lxc_conf->personality = personality;
else
WARN("Unsupported personality \"%s\"", value);
ret = lxc_config_parse_arch(value, &personality);
if (ret < 0)
return syserror("Unsupported personality \"%s\"", value);
lxc_conf->personality = personality;
return 0;
}
......@@ -3213,10 +3209,9 @@ void lxc_config_define_free(struct lxc_list *defines)
}
}
signed long lxc_config_parse_arch(const char *arch)
int lxc_config_parse_arch(const char *arch, signed long *persona)
{
#if HAVE_SYS_PERSONALITY_H
struct per_name {
static struct per_name {
char *name;
unsigned long per;
} pername[] = {
......@@ -3247,14 +3242,16 @@ signed long lxc_config_parse_arch(const char *arch)
{ "s390x", PER_LINUX },
{ "x86_64", PER_LINUX },
};
size_t len = sizeof(pername) / sizeof(pername[0]);
for (int i = 0; i < len; i++)
if (strequal(pername[i].name, arch))
return pername[i].per;
#endif
for (int i = 0; i < ARRAY_SIZE(pername); i++) {
if (!strequal(pername[i].name, arch))
continue;
*persona = pername[i].per;
return 0;
}
return LXC_ARCH_UNCHANGED;
return ret_errno(EINVAL);
}
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
......@@ -3735,7 +3732,6 @@ static int get_config_personality(const char *key, char *retv, int inlen,
else
memset(retv, 0, inlen);
#if HAVE_SYS_PERSONALITY_H
int len = 0;
switch (c->personality) {
......@@ -3748,7 +3744,6 @@ static int get_config_personality(const char *key, char *retv, int inlen,
default:
break;
}
#endif
return fulllen;
}
......
......@@ -84,11 +84,10 @@ __hidden extern void lxc_config_define_free(struct lxc_list *defines);
#define LXC_ARCH_UNCHANGED 0xffffffffL
/*
* Parse personality of the container. Returns LXC_ARCH_UNCHANGED if the
* personality is not know.
* (Used during attach.)
* Parse personality of the container. Returns 0 if personality is valid,
* negative errno otherwise.
*/
__hidden extern signed long lxc_config_parse_arch(const char *arch);
__hidden extern int lxc_config_parse_arch(const char *arch, signed long *persona);
__hidden extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
......
......@@ -22,6 +22,7 @@
#include <unistd.h>
#include "compiler.h"
#include "config.h"
#ifndef PATH_MAX
#define PATH_MAX 4096
......@@ -741,4 +742,9 @@ enum {
#define BITS_PER_TYPE(type) (sizeof(type) * 8)
#define LAST_BIT_PER_TYPE(type) (BITS_PER_TYPE(type) - 1)
#ifndef HAVE_SYS_PERSONALITY_H
#define PER_LINUX 0x0000
#define PER_LINUX32 0x0008
#endif
#endif /* __LXC_MACRO_H */
......@@ -700,4 +700,43 @@
#endif
#endif
#ifndef __NR_personality
#if defined __alpha__
#define __NR_personality 324
#elif defined __m68k__
#define __NR_personality 136
#elif defined __i386__
#define __NR_personality 136
#elif defined __x86_64__
#define __NR_personality 135
#elif defined __arm__
#define __NR_personality 136
#elif defined __aarch64__
#define __NR_personality 92
#elif defined __s390__
#define __NR_personality 136
#elif defined __powerpc__
#define __NR_personality 136
#elif defined __riscv
#define __NR_personality -1
#elif defined __sparc__
#define __NR_personality 191
#elif defined __ia64__
#define __NR_personality (116 + 1024)
#elif defined _MIPS_SIM
#if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
#define __NR_personality (136 + 4000)
#endif
#if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
#define __NR_personality (132 + 6000)
#endif
#if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
#define __NR_personality (132 + 5000)
#endif
#else
#define -1
#warning "__NR_personality not defined for your architecture"
#endif
#endif
#endif /* __LXC_SYSCALL_NUMBERS_H */
......@@ -31,6 +31,10 @@
#include <linux/openat2.h>
#endif
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
typedef int32_t key_serial_t;
#if !HAVE_KEYCTL
......@@ -317,4 +321,11 @@ static inline int close_range(unsigned int fd, unsigned int max_fd, unsigned int
}
#endif
#ifndef HAVE_SYS_PERSONALITY_H
static inline int personality(unsigned long persona)
{
return syscall(__NR_personality, persona);
}
#endif
#endif /* __LXC_SYSCALL_WRAPPER_H */
......@@ -154,8 +154,8 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
break;
case 'R': remount_sys_proc = 1; break;
case 'a':
new_personality = lxc_config_parse_arch(arg);
if (new_personality < 0) {
ret = lxc_config_parse_arch(arg, &new_personality);
if (ret < 0) {
ERROR("Invalid architecture specified: %s", arg);
return -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment