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