conf: ease backports by carrying unused structs

parent d87de00d
...@@ -928,7 +928,9 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops, ...@@ -928,7 +928,9 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
goto cgroup_prune_tree; goto cgroup_prune_tree;
} }
if (conf->cgroup_meta.dir) if (conf->cgroup_meta.monitor_pivot_dir)
pivot_path = must_make_path(conf->cgroup_meta.monitor_pivot_dir, CGROUP_PIVOT, NULL);
else if (conf->cgroup_meta.dir)
pivot_path = must_make_path(conf->cgroup_meta.dir, CGROUP_PIVOT, NULL); pivot_path = must_make_path(conf->cgroup_meta.dir, CGROUP_PIVOT, NULL);
else else
pivot_path = must_make_path(CGROUP_PIVOT, NULL); pivot_path = must_make_path(CGROUP_PIVOT, NULL);
......
...@@ -2717,6 +2717,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2717,6 +2717,7 @@ struct lxc_conf *lxc_conf_init(void)
memset(&new->init_groups, 0, sizeof(lxc_groups_t)); memset(&new->init_groups, 0, sizeof(lxc_groups_t));
memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup)); memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX); memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX);
memset(&new->timens, 0, sizeof(struct timens_offsets));
seccomp_conf_init(new); seccomp_conf_init(new);
return new; return new;
...@@ -3967,6 +3968,10 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3967,6 +3968,10 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_apparmor_raw(conf); lxc_clear_apparmor_raw(conf);
lxc_clear_namespace(conf); lxc_clear_namespace(conf);
free(conf->cgroup_meta.dir); free(conf->cgroup_meta.dir);
free(conf->cgroup_meta.monitor_dir);
free(conf->cgroup_meta.monitor_pivot_dir);
free(conf->cgroup_meta.container_dir);
free(conf->cgroup_meta.namespace_dir);
free(conf->cgroup_meta.controllers); free(conf->cgroup_meta.controllers);
free(conf->shmount.path_host); free(conf->shmount.path_host);
free(conf->shmount.path_cont); free(conf->shmount.path_cont);
......
...@@ -65,6 +65,7 @@ struct lxc_cgroup { ...@@ -65,6 +65,7 @@ struct lxc_cgroup {
char *controllers; char *controllers;
char *dir; char *dir;
char *monitor_dir; char *monitor_dir;
char *monitor_pivot_dir;
char *container_dir; char *container_dir;
char *namespace_dir; char *namespace_dir;
bool relative; bool relative;
...@@ -286,6 +287,16 @@ struct bpf_devices { ...@@ -286,6 +287,16 @@ struct bpf_devices {
struct lxc_list device_item; struct lxc_list device_item;
}; };
struct timens_offsets {
/* Currently, either s_boot or ns_boot is set, but not both. */
int64_t s_boot;
int64_t ns_boot;
/* Currently, either s_monotonic or ns_monotonic is set, but not both. */
int64_t s_monotonic;
int64_t ns_monotonic;
};
struct lxc_conf { struct lxc_conf {
/* Pointer to the name of the container. Do not free! */ /* Pointer to the name of the container. Do not free! */
const char *name; const char *name;
...@@ -456,6 +467,8 @@ struct lxc_conf { ...@@ -456,6 +467,8 @@ struct lxc_conf {
/* Absolute path (in the container) to the shared mount point */ /* Absolute path (in the container) to the shared mount point */
char *path_cont; char *path_cont;
} shmount; } shmount;
struct timens_offsets timens;
}; };
__hidden extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, size_t buf_size) __hidden extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, size_t buf_size)
......
...@@ -82,6 +82,7 @@ __hidden extern FILE *fdopen_at(int dfd, const char *path, const char *mode, ...@@ -82,6 +82,7 @@ __hidden extern FILE *fdopen_at(int dfd, const char *path, const char *mode,
unsigned int o_flags, unsigned int o_flags,
unsigned int resolve_flags); unsigned int resolve_flags);
__hidden extern FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer); __hidden extern FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer);
__hidden extern int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset);
__hidden extern bool exists_dir_at(int dir_fd, const char *path); __hidden extern bool exists_dir_at(int dir_fd, const char *path);
__hidden extern bool exists_file_at(int dir_fd, const char *path); __hidden extern bool exists_file_at(int dir_fd, const char *path);
__hidden extern int open_at(int dfd, const char *path, unsigned int o_flags, __hidden extern int open_at(int dfd, const char *path, unsigned int o_flags,
......
...@@ -45,6 +45,7 @@ const struct ns_info ns_info[LXC_NS_MAX] = { ...@@ -45,6 +45,7 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
[LXC_NS_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" }, [LXC_NS_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" },
[LXC_NS_NET] = { "net", "ns/net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" }, [LXC_NS_NET] = { "net", "ns/net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" },
[LXC_NS_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" }, [LXC_NS_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" },
[LXC_NS_TIME] = { "time", "ns/time", CLONE_NEWTIME, "CLONE_NEWTIME", "LXC_TIME_NS" },
}; };
int lxc_namespace_2_cloneflag(const char *namespace) int lxc_namespace_2_cloneflag(const char *namespace)
......
...@@ -17,6 +17,7 @@ typedef enum lxc_namespace_t { ...@@ -17,6 +17,7 @@ typedef enum lxc_namespace_t {
LXC_NS_IPC = 4, LXC_NS_IPC = 4,
LXC_NS_NET = 5, LXC_NS_NET = 5,
LXC_NS_CGROUP = 6, LXC_NS_CGROUP = 6,
LXC_NS_TIME = 7,
LXC_NS_MAX = 8 LXC_NS_MAX = 8
} lxc_namespace_t; } lxc_namespace_t;
......
...@@ -1197,6 +1197,55 @@ static int do_start(void *data) ...@@ -1197,6 +1197,55 @@ static int do_start(void *data)
} }
} }
if (handler->ns_unshare_flags & CLONE_NEWTIME) {
ret = unshare(CLONE_NEWTIME);
if (ret < 0) {
if (errno != EINVAL) {
SYSERROR("Failed to unshare CLONE_NEWTIME");
goto out_warn_father;
}
handler->ns_clone_flags &= ~CLONE_NEWTIME;
SYSINFO("Kernel does not support CLONE_NEWTIME");
} else {
__do_close int timens_fd = -EBADF;
INFO("Unshared CLONE_NEWTIME");
if (handler->conf->timens.s_boot)
ret = timens_offset_write(CLOCK_BOOTTIME, handler->conf->timens.s_boot, 0);
else if (handler->conf->timens.ns_boot)
ret = timens_offset_write(CLOCK_BOOTTIME, 0, handler->conf->timens.ns_boot);
if (ret) {
SYSERROR("Failed to write CLONE_BOOTTIME offset");
goto out_warn_father;
}
TRACE("Wrote CLOCK_BOOTTIME offset");
if (handler->conf->timens.s_monotonic)
ret = timens_offset_write(CLOCK_MONOTONIC, handler->conf->timens.s_monotonic, 0);
else if (handler->conf->timens.ns_monotonic)
ret = timens_offset_write(CLOCK_MONOTONIC, 0, handler->conf->timens.ns_monotonic);
if (ret) {
SYSERROR("Failed to write CLONE_MONOTONIC offset");
goto out_warn_father;
}
TRACE("Wrote CLOCK_MONOTONIC offset");
timens_fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
if (timens_fd < 0) {
SYSERROR("Failed to open \"/proc/self/ns/time_for_children\"");
goto out_warn_father;
}
ret = setns(timens_fd, CLONE_NEWTIME);
if (ret) {
SYSERROR("Failed to setns(%d(\"/proc/self/ns/time_for_children\"))", timens_fd);
goto out_warn_father;
}
}
}
/* Add the requested environment variables to the current environment to /* Add the requested environment variables to the current environment to
* allow them to be used by the various hooks, such as the start hook * allow them to be used by the various hooks, such as the start hook
* below. * below.
...@@ -1434,6 +1483,8 @@ int resolve_clone_flags(struct lxc_handler *handler) ...@@ -1434,6 +1483,8 @@ int resolve_clone_flags(struct lxc_handler *handler)
{ {
int i; int i;
struct lxc_conf *conf = handler->conf; struct lxc_conf *conf = handler->conf;
bool wants_timens = conf->timens.s_boot || conf->timens.ns_boot ||
conf->timens.s_monotonic || conf->timens.ns_monotonic;
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if (conf->ns_keep) { if (conf->ns_keep) {
...@@ -1452,6 +1503,9 @@ int resolve_clone_flags(struct lxc_handler *handler) ...@@ -1452,6 +1503,9 @@ int resolve_clone_flags(struct lxc_handler *handler)
if (i == LXC_NS_CGROUP && !cgns_supported()) if (i == LXC_NS_CGROUP && !cgns_supported())
continue; continue;
if (i == LXC_NS_TIME && !wants_timens)
continue;
handler->ns_clone_flags |= ns_info[i].clone_flag; handler->ns_clone_flags |= ns_info[i].clone_flag;
} }
...@@ -1462,6 +1516,13 @@ int resolve_clone_flags(struct lxc_handler *handler) ...@@ -1462,6 +1516,13 @@ int resolve_clone_flags(struct lxc_handler *handler)
TRACE("Sharing %s namespace", ns_info[i].proc_name); TRACE("Sharing %s namespace", ns_info[i].proc_name);
} }
if (wants_timens && (conf->ns_keep & ns_info[LXC_NS_TIME].clone_flag))
return log_trace_errno(-1, EINVAL, "Requested to keep time namespace while also specifying offsets");
/* Deal with namespaces that are unshared. */
if (handler->ns_clone_flags & CLONE_NEWTIME)
handler->ns_unshare_flags |= CLONE_NEWTIME;
if (!pure_unified_layout(handler->cgroup_ops) && handler->ns_clone_flags & CLONE_NEWCGROUP) if (!pure_unified_layout(handler->cgroup_ops) && handler->ns_clone_flags & CLONE_NEWCGROUP)
handler->ns_unshare_flags |= CLONE_NEWCGROUP; handler->ns_unshare_flags |= CLONE_NEWCGROUP;
...@@ -1830,6 +1891,17 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1830,6 +1891,17 @@ static int lxc_spawn(struct lxc_handler *handler)
cgroup_ops->finalize(cgroup_ops); cgroup_ops->finalize(cgroup_ops);
TRACE("Finished setting up cgroups"); TRACE("Finished setting up cgroups");
if (handler->ns_unshare_flags & CLONE_NEWTIME) {
/* Now we're ready to preserve the time namespace */
ret = lxc_try_preserve_namespace(handler, LXC_NS_TIME, "time");
if (ret < 0) {
if (ret != -ENOENT) {
SYSERROR("Failed to preserve time namespace");
goto out_delete_net;
}
}
}
/* Run any host-side start hooks */ /* Run any host-side start hooks */
ret = run_lxc_hooks(name, "start-host", conf, NULL); ret = run_lxc_hooks(name, "start-host", conf, NULL);
if (ret < 0) { if (ret < 0) {
......
...@@ -665,6 +665,51 @@ int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base) ...@@ -665,6 +665,51 @@ int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base)
return 0; return 0;
} }
int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base, char *residual,
size_t residual_len)
{
char *remaining = NULL;
int64_t u;
if (residual && residual_len == 0)
return ret_errno(EINVAL);
if (!residual && residual_len != 0)
return ret_errno(EINVAL);
while (isspace(*numstr))
numstr++;
errno = 0;
u = strtoll(numstr, &remaining, base);
if (errno == ERANGE && u == INT64_MAX)
return -ERANGE;
if (remaining == numstr)
return -EINVAL;
if (residual) {
size_t len = 0;
if (*remaining == '\0') {
memset(residual, 0, residual_len);
goto out;
}
len = strlen(remaining);
if (len >= residual_len)
return -EINVAL;
memcpy(residual, remaining, len);
} else if (*remaining != '\0') {
return -EINVAL;
}
out:
*converted = u;
return 0;
}
int lxc_safe_int(const char *numstr, int *converted) int lxc_safe_int(const char *numstr, int *converted)
{ {
char *err = NULL; char *err = NULL;
......
...@@ -74,6 +74,8 @@ __hidden extern int lxc_safe_long(const char *numstr, long int *converted); ...@@ -74,6 +74,8 @@ __hidden extern int lxc_safe_long(const char *numstr, long int *converted);
__hidden extern int lxc_safe_long_long(const char *numstr, long long int *converted); __hidden extern int lxc_safe_long_long(const char *numstr, long long int *converted);
__hidden extern int lxc_safe_ulong(const char *numstr, unsigned long *converted); __hidden extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
__hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base); __hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base);
__hidden extern int lxc_safe_int64_residual(const char *numstr, int64_t *converted, int base,
char *residual, size_t residual_len);
/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */ /* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
__hidden extern int parse_byte_size_string(const char *s, int64_t *converted); __hidden extern int parse_byte_size_string(const char *s, int64_t *converted);
......
...@@ -1844,6 +1844,18 @@ int fix_stdio_permissions(uid_t uid) ...@@ -1844,6 +1844,18 @@ int fix_stdio_permissions(uid_t uid)
return fret; return fret;
} }
bool multiply_overflow(int64_t base, uint64_t mult, int64_t *res)
{
if (base > 0 && base > (INT64_MAX / mult))
return false;
if (base < 0 && base < (INT64_MIN / mult))
return false;
*res = base * mult;
return true;
}
int print_r(int fd, const char *path) int print_r(int fd, const char *path)
{ {
__do_close int dfd = -EBADF, dfd_dup = -EBADF; __do_close int dfd = -EBADF, dfd_dup = -EBADF;
......
...@@ -237,6 +237,8 @@ static inline bool gid_valid(gid_t gid) ...@@ -237,6 +237,8 @@ static inline bool gid_valid(gid_t gid)
return gid != LXC_INVALID_GID; return gid != LXC_INVALID_GID;
} }
__hidden extern bool multiply_overflow(int64_t base, uint64_t mult, int64_t *res);
__hidden extern int safe_mount_beneath(const char *beneath, const char *src, const char *dst, __hidden extern int safe_mount_beneath(const char *beneath, const char *src, const char *dst,
const char *fstype, unsigned int flags, const void *data); const char *fstype, unsigned int flags, const void *data);
__hidden extern int safe_mount_beneath_at(int beneat_fd, const char *src, const char *dst, __hidden extern int safe_mount_beneath_at(int beneat_fd, const char *src, const char *dst,
......
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