tools: move lxc-attach to API symbols only

Closes #2073. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 3fb8253d
......@@ -4,7 +4,6 @@ pkginclude_HEADERS = \
version.h
noinst_HEADERS = \
tools/arguments.h \
attach.h \
storage/storage.h \
storage/aufs.h \
......@@ -18,6 +17,9 @@ noinst_HEADERS = \
storage/rsync.h \
storage/zfs.h \
storage/storage_utils.h \
tools/arguments.h \
tools/tool_utils.h \
tools/tool_list.h \
cgroups/cgroup.h \
cgroups/cgroup_utils.h \
caps.h \
......@@ -266,7 +268,7 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
endif
LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c
lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c
lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c
lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c
lxc_config_SOURCES = tools/lxc_config.c tools/arguments.c
......
......@@ -2409,47 +2409,6 @@ signed long lxc_config_parse_arch(const char *arch)
return -1;
}
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int i, aflag;
struct {
const char *token;
int flag;
} all_privs[] = {
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
};
if (!flaglist) {
/* For the sake of backward compatibility, drop all privileges
* if none is specified.
*/
for (i = 0; all_privs[i].token; i++)
*flags |= all_privs[i].flag;
return 0;
}
token = strtok_r(flaglist, "|", &saveptr);
while (token) {
aflag = -1;
for (i = 0; all_privs[i].token; i++)
if (!strcmp(all_privs[i].token, token))
aflag = all_privs[i].flag;
if (aflag < 0)
return -1;
*flags |= aflag;
token = strtok_r(NULL, "|", &saveptr);
}
return 0;
}
/* Write out a configuration file. */
void write_config(FILE *fout, struct lxc_conf *c)
{
......
......@@ -92,8 +92,6 @@ extern int lxc_config_define_load(struct lxc_list *defines,
/* needed for lxc-attach */
extern signed long lxc_config_parse_arch(const char *arch);
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
extern void write_config(FILE *fout, struct lxc_conf *c);
......
......@@ -182,6 +182,13 @@ static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
return 0;
}
void remove_trailing_slashes(char *p)
{
int l = strlen(p);
while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
p[l] = '\0';
}
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
char *const argv[])
{
......@@ -250,7 +257,7 @@ extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
/* If no lxcpaths were given, use default */
if (!args->lxcpath_cnt) {
ret = lxc_arguments_lxcpath_add(
args, lxc_global_config_value("lxc.lxcpath"));
args, lxc_get_global_config_item("lxc.lxcpath"));
if (ret < 0)
return ret;
}
......
......@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
......@@ -36,16 +37,8 @@
#include <lxc/lxccontainer.h>
#include "attach.h"
#include "arguments.h"
#include "caps.h"
#include "conf.h"
#include "confile.h"
#include "console.h"
#include "log.h"
#include "list.h"
#include "mainloop.h"
#include "utils.h"
#include "tool_utils.h"
static const struct option my_longopts[] = {
{"elevated-privileges", optional_argument, 0, 'e'},
......@@ -290,7 +283,6 @@ int main(int argc, char *argv[])
r = lxc_log_init(&log);
if (r)
exit(EXIT_FAILURE);
lxc_log_options_no_override();
if (geteuid()) {
if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
......
......@@ -24,7 +24,6 @@
#include <lxc/lxccontainer.h>
#include "arguments.h"
#include "list.h"
#include "log.h"
#include "utils.h"
......
/* liblxcapi
*
* Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
* Copyright © 2018 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <linux/sched.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
#include <lxc/lxccontainer.h>
#include "tool_utils.h"
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int i, aflag;
struct {
const char *token;
int flag;
} all_privs[] = {
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
};
if (!flaglist) {
/* For the sake of backward compatibility, drop all privileges
* if none is specified.
*/
for (i = 0; all_privs[i].token; i++)
*flags |= all_privs[i].flag;
return 0;
}
token = strtok_r(flaglist, "|", &saveptr);
while (token) {
aflag = -1;
for (i = 0; all_privs[i].token; i++)
if (!strcmp(all_privs[i].token, token))
aflag = all_privs[i].flag;
if (aflag < 0)
return -1;
*flags |= aflag;
token = strtok_r(NULL, "|", &saveptr);
}
return 0;
}
signed long lxc_config_parse_arch(const char *arch)
{
#if HAVE_SYS_PERSONALITY_H
size_t i;
struct per_name {
char *name;
unsigned long per;
} pername[] = {
{ "x86", PER_LINUX32 },
{ "linux32", PER_LINUX32 },
{ "i386", PER_LINUX32 },
{ "i486", PER_LINUX32 },
{ "i586", PER_LINUX32 },
{ "i686", PER_LINUX32 },
{ "athlon", PER_LINUX32 },
{ "mips", PER_LINUX32 },
{ "mipsel", PER_LINUX32 },
{ "ppc", PER_LINUX32 },
{ "arm", PER_LINUX32 },
{ "armv7l", PER_LINUX32 },
{ "armhf", PER_LINUX32 },
{ "armel", PER_LINUX32 },
{ "powerpc", PER_LINUX32 },
{ "linux64", PER_LINUX },
{ "x86_64", PER_LINUX },
{ "amd64", PER_LINUX },
{ "mips64", PER_LINUX },
{ "mips64el", PER_LINUX },
{ "ppc64", PER_LINUX },
{ "ppc64le", PER_LINUX },
{ "ppc64el", PER_LINUX },
{ "powerpc64", PER_LINUX },
{ "s390x", PER_LINUX },
{ "aarch64", PER_LINUX },
{ "arm64", PER_LINUX },
};
size_t len = sizeof(pername) / sizeof(pername[0]);
for (i = 0; i < len; i++) {
if (!strcmp(pername[i].name, arch))
return pername[i].per;
}
#endif
return -1;
}
enum {
LXC_NS_USER,
LXC_NS_MNT,
LXC_NS_PID,
LXC_NS_UTS,
LXC_NS_IPC,
LXC_NS_NET,
LXC_NS_CGROUP,
LXC_NS_MAX
};
const static struct ns_info {
const char *proc_name;
int clone_flag;
} ns_info[LXC_NS_MAX] = {
[LXC_NS_USER] = { "user", CLONE_NEWUSER },
[LXC_NS_MNT] = { "mnt", CLONE_NEWNS },
[LXC_NS_PID] = { "pid", CLONE_NEWPID },
[LXC_NS_UTS] = { "uts", CLONE_NEWUTS },
[LXC_NS_IPC] = { "ipc", CLONE_NEWIPC },
[LXC_NS_NET] = { "net", CLONE_NEWNET },
[LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP }
};
int lxc_namespace_2_cloneflag(const char *namespace)
{
int i;
for (i = 0; i < LXC_NS_MAX; i++)
if (!strcasecmp(ns_info[i].proc_name, namespace))
return ns_info[i].clone_flag;
fprintf(stderr, "Invalid namespace name \"%s\"", namespace);
return -EINVAL;
}
int lxc_fill_namespace_flags(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int aflag;
if (!flaglist) {
fprintf(stderr, "At least one namespace is needed\n");
return -1;
}
token = strtok_r(flaglist, "|", &saveptr);
while (token) {
aflag = lxc_namespace_2_cloneflag(token);
if (aflag < 0)
return -1;
*flags |= aflag;
token = strtok_r(NULL, "|", &saveptr);
}
return 0;
}
#if HAVE_LIBCAP
#ifndef PR_CAPBSET_READ
#define PR_CAPBSET_READ 23
#endif
int lxc_caps_init(void)
{
uid_t uid = getuid();
gid_t gid = getgid();
uid_t euid = geteuid();
if (!uid)
return 0;
if (uid && !euid) {
if (prctl(PR_SET_KEEPCAPS, 1)) {
fprintf(stderr, "%s - Failed to set PR_SET_KEEPCAPS\n", strerror(errno));
return -1;
}
if (setresgid(gid, gid, gid)) {
fprintf(stderr, "%s - Failed to change gid to %d\n", strerror(errno), gid);
return -1;
}
if (setresuid(uid, uid, uid)) {
fprintf(stderr, "%s - Failed to change uid to %d\n", strerror(errno), uid);
return -1;
}
if (lxc_caps_up()) {
fprintf(stderr, "%s - Failed to restore capabilities\n", strerror(errno));
return -1;
}
}
return 0;
}
int lxc_caps_up(void)
{
cap_t caps;
cap_value_t cap;
int ret;
/* when we are run as root, we don't want to play
* with the capabilities */
if (!getuid())
return 0;
caps = cap_get_proc();
if (!caps) {
fprintf(stderr, "%s - Failed to cap_get_proc\n", strerror(errno));
return -1;
}
for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
cap_flag_value_t flag;
ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
if (ret) {
if (errno == EINVAL) {
break;
} else {
fprintf(stderr, "%s- Failed to call cap_get_flag\n", strerror(errno));
goto out;
}
}
ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
if (ret) {
fprintf(stderr, "%s - Failed to call cap_set_flag", strerror(errno));
goto out;
}
}
ret = cap_set_proc(caps);
if (ret) {
fprintf(stderr, "%s - Failed to cap_set_proc", strerror(errno));
goto out;
}
out:
cap_free(caps);
return 0;
}
#endif
int lxc_wait_for_pid_status(pid_t pid)
{
int status, ret;
again:
ret = waitpid(pid, &status, 0);
if (ret == -1) {
if (errno == EINTR)
goto again;
return -1;
}
if (ret != pid)
goto again;
return status;
}
int lxc_safe_int(const char *numstr, int *converted)
{
char *err = NULL;
signed long int sli;
errno = 0;
sli = strtol(numstr, &err, 0);
if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
return -ERANGE;
if (errno != 0 && sli == 0)
return -EINVAL;
if (err == numstr || *err != '\0')
return -EINVAL;
if (sli > INT_MAX || sli < INT_MIN)
return -ERANGE;
*converted = (int)sli;
return 0;
}
int lxc_safe_long(const char *numstr, long int *converted)
{
char *err = NULL;
signed long int sli;
errno = 0;
sli = strtol(numstr, &err, 0);
if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
return -ERANGE;
if (errno != 0 && sli == 0)
return -EINVAL;
if (err == numstr || *err != '\0')
return -EINVAL;
*converted = sli;
return 0;
}
/* liblxcapi
*
* Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
* Copyright © 2018 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __LXC_UTILS_H
#define __LXC_UTILS_H
/* Properly support loop devices on 32bit systems. */
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <lxc/lxccontainer.h>
#include "tool_list.h"
#define TOOL_MAXPATHLEN 4096
#ifndef CLONE_PARENT_SETTID
#define CLONE_PARENT_SETTID 0x00100000
#endif
#ifndef CLONE_CHILD_CLEARTID
#define CLONE_CHILD_CLEARTID 0x00200000
#endif
#ifndef CLONE_CHILD_SETTID
#define CLONE_CHILD_SETTID 0x01000000
#endif
#ifndef CLONE_VFORK
#define CLONE_VFORK 0x00004000
#endif
#ifndef CLONE_THREAD
#define CLONE_THREAD 0x00010000
#endif
#ifndef CLONE_SETTLS
#define CLONE_SETTLS 0x00080000
#endif
#ifndef CLONE_VM
#define CLONE_VM 0x00000100
#endif
#ifndef CLONE_FILES
#define CLONE_FILES 0x00000400
#endif
#ifndef CLONE_FS
# define CLONE_FS 0x00000200
#endif
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
#ifndef CLONE_NEWCGROUP
# define CLONE_NEWCGROUP 0x02000000
#endif
#ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWUSER
# define CLONE_NEWUSER 0x10000000
#endif
#ifndef CLONE_NEWPID
# define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
enum {
LXC_NS_USER,
LXC_NS_MNT,
LXC_NS_PID,
LXC_NS_UTS,
LXC_NS_IPC,
LXC_NS_NET,
LXC_NS_CGROUP,
LXC_NS_MAX
};
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);
extern signed long lxc_config_parse_arch(const char *arch);
extern int lxc_namespace_2_cloneflag(const char *namespace);
extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
#if HAVE_LIBCAP
#include <sys/capability.h>
extern int lxc_caps_up(void);
extern int lxc_caps_init(void);
#else
static inline int lxc_caps_up(void) {
return 0;
}
static inline int lxc_caps_init(void) {
return 0;
}
#endif
extern int lxc_wait_for_pid_status(pid_t pid);
extern int lxc_safe_int(const char *numstr, int *converted);
extern int lxc_safe_long(const char *numstr, long int *converted);
#endif /* __LXC_UTILS_H */
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