mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-25 20:25:27 +00:00
confile: add lxc.proc.* to set proc filesystem
Signed-off-by: Yifeng Tan <tanyifeng1@huawei.com>
This commit is contained in:
parent
f449521ce6
commit
61d7a733c7
@ -338,6 +338,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Proc</title>
|
||||
<para>
|
||||
Configure proc filesystem for the container.
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>lxc.proc.[proc file name]</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specify the proc file name to be set. The file name available
|
||||
are those listed under /proc/PID/.
|
||||
Example:
|
||||
</para>
|
||||
<programlisting>
|
||||
lxc.proc.oom_score_adj = 10
|
||||
</programlisting>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Ephemeral</title>
|
||||
<para>
|
||||
|
@ -2398,6 +2398,38 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
|
||||
{
|
||||
struct lxc_list *it;
|
||||
struct lxc_proc *elem;
|
||||
char *tmp = NULL;
|
||||
char filename[MAXPATHLEN] = {0};
|
||||
int ret = 0;
|
||||
|
||||
lxc_list_for_each(it, procs) {
|
||||
elem = it->elem;
|
||||
tmp = lxc_string_replace(".", "/", elem->filename);
|
||||
if (!tmp) {
|
||||
ERROR("Failed to replace key %s", elem->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, tmp);
|
||||
free(tmp);
|
||||
if (ret < 0 || (size_t)ret >= sizeof(filename)) {
|
||||
ERROR("Error setting up proc filesystem path");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lxc_write_to_file(filename, elem->value, strlen(elem->value), false);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to setup proc filesystem %s to %s", elem->filename, elem->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *default_rootfs_mount = LXCROOTFSMOUNT;
|
||||
|
||||
struct lxc_conf *lxc_conf_init(void)
|
||||
@ -2449,6 +2481,7 @@ struct lxc_conf *lxc_conf_init(void)
|
||||
lxc_list_init(&new->environment);
|
||||
lxc_list_init(&new->limits);
|
||||
lxc_list_init(&new->sysctls);
|
||||
lxc_list_init(&new->procs);
|
||||
for (i = 0; i < NUM_LXC_HOOKS; i++)
|
||||
lxc_list_init(&new->hooks[i]);
|
||||
lxc_list_init(&new->groups);
|
||||
@ -3384,6 +3417,33 @@ int lxc_clear_sysctls(struct lxc_conf *c, const char *key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_clear_procs(struct lxc_conf *c, const char *key)
|
||||
{
|
||||
struct lxc_list *it,*next;
|
||||
bool all = false;
|
||||
const char *k = NULL;
|
||||
|
||||
if (strcmp(key, "lxc.proc") == 0)
|
||||
all = true;
|
||||
else if (strncmp(key, "lxc.proc.", sizeof("lxc.proc.") - 1) == 0)
|
||||
k = key + sizeof("lxc.proc.") - 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
lxc_list_for_each_safe(it, &c->procs, next) {
|
||||
struct lxc_proc *proc = it->elem;
|
||||
if (!all && strcmp(proc->filename, k) != 0)
|
||||
continue;
|
||||
lxc_list_del(it);
|
||||
free(proc->filename);
|
||||
free(proc->value);
|
||||
free(proc);
|
||||
free(it);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_clear_groups(struct lxc_conf *c)
|
||||
{
|
||||
struct lxc_list *it,*next;
|
||||
@ -3524,6 +3584,7 @@ void lxc_conf_free(struct lxc_conf *conf)
|
||||
lxc_clear_environment(conf);
|
||||
lxc_clear_limits(conf, "lxc.prlimit");
|
||||
lxc_clear_sysctls(conf, "lxc.sysctl");
|
||||
lxc_clear_procs(conf, "lxc.proc");
|
||||
free(conf->cgroup_meta.dir);
|
||||
free(conf->cgroup_meta.controllers);
|
||||
free(conf);
|
||||
|
@ -105,6 +105,16 @@ struct lxc_sysctl {
|
||||
char *value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Defines a structure to configure proc filesystem at runtime.
|
||||
* @filename : the proc filesystem will be configured without the "lxc.proc" prefix
|
||||
* @value : the value to set
|
||||
*/
|
||||
struct lxc_proc {
|
||||
char *filename;
|
||||
char *value;
|
||||
};
|
||||
|
||||
/*
|
||||
* id_map is an id map entry. Form in confile is:
|
||||
* lxc.idmap = u 0 9800 100
|
||||
@ -383,6 +393,9 @@ struct lxc_conf {
|
||||
|
||||
/* sysctls */
|
||||
struct lxc_list sysctls;
|
||||
|
||||
/* procs */
|
||||
struct lxc_list procs;
|
||||
};
|
||||
|
||||
int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
|
||||
@ -443,5 +456,7 @@ extern int run_script(const char *name, const char *section, const char *script,
|
||||
extern int in_caplist(int cap, struct lxc_list *caps);
|
||||
extern int setup_sysctl_parameters(struct lxc_list *sysctls);
|
||||
extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
|
||||
extern int setup_proc_filesystem(struct lxc_list *procs, pid_t pid);
|
||||
extern int lxc_clear_procs(struct lxc_conf *c, const char *key);
|
||||
|
||||
#endif /* __LXC_CONF_H */
|
||||
|
@ -142,6 +142,7 @@ lxc_config_define(tty_max);
|
||||
lxc_config_define(tty_dir);
|
||||
lxc_config_define(uts_name);
|
||||
lxc_config_define(sysctl);
|
||||
lxc_config_define(proc);
|
||||
|
||||
static struct lxc_config_t config[] = {
|
||||
/* REMOVE in LXC 3.0 */
|
||||
@ -243,6 +244,7 @@ static struct lxc_config_t config[] = {
|
||||
{ "lxc.tty.max", false, set_config_tty_max, get_config_tty_max, clr_config_tty_max, },
|
||||
{ "lxc.uts.name", false, set_config_uts_name, get_config_uts_name, clr_config_uts_name, },
|
||||
{ "lxc.sysctl", false, set_config_sysctl, get_config_sysctl, clr_config_sysctl, },
|
||||
{ "lxc.proc", false, set_config_proc, get_config_proc, clr_config_proc, },
|
||||
|
||||
/* [START]: REMOVE IN LXC 3.0 */
|
||||
{ "lxc.pts", true, set_config_pty_max, get_config_pty_max, clr_config_pty_max, },
|
||||
@ -1562,6 +1564,55 @@ on_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int set_config_proc(const char *key, const char *value,
|
||||
struct lxc_conf *lxc_conf, void *data)
|
||||
{
|
||||
const char *subkey;
|
||||
struct lxc_list *proclist = NULL;
|
||||
struct lxc_proc *procelem = NULL;
|
||||
|
||||
if (lxc_config_value_empty(value))
|
||||
return clr_config_proc(key, lxc_conf, NULL);
|
||||
|
||||
if (strncmp(key, "lxc.proc.", sizeof("lxc.proc.") -1) != 0)
|
||||
return -1;
|
||||
|
||||
subkey = key + sizeof("lxc.proc.") - 1;
|
||||
if (*subkey == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
proclist = malloc(sizeof(*proclist));
|
||||
if (!proclist)
|
||||
goto on_error;
|
||||
|
||||
procelem = malloc(sizeof(*procelem));
|
||||
if (!procelem)
|
||||
goto on_error;
|
||||
memset(procelem, 0, sizeof(*procelem));
|
||||
|
||||
procelem->filename = strdup(subkey);
|
||||
procelem->value = strdup(value);
|
||||
|
||||
if (!procelem->filename || !procelem->value)
|
||||
goto on_error;
|
||||
|
||||
proclist->elem = procelem;
|
||||
|
||||
lxc_list_add_tail(&lxc_conf->procs, proclist);
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
free(proclist);
|
||||
if (procelem) {
|
||||
free(procelem->filename);
|
||||
free(procelem->value);
|
||||
free(procelem);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int set_config_idmaps(const char *key, const char *value,
|
||||
struct lxc_conf *lxc_conf, void *data)
|
||||
{
|
||||
@ -3414,6 +3465,40 @@ static int get_config_sysctl(const char *key, char *retv, int inlen,
|
||||
return fulllen;
|
||||
}
|
||||
|
||||
static int get_config_proc(const char *key, char *retv, int inlen,
|
||||
struct lxc_conf *c, void *data)
|
||||
{
|
||||
struct lxc_list *it;
|
||||
int len;
|
||||
int fulllen = 0;
|
||||
bool get_all = false;
|
||||
|
||||
if (!retv)
|
||||
inlen = 0;
|
||||
else
|
||||
memset(retv, 0, inlen);
|
||||
|
||||
if (strcmp(key, "lxc.proc") == 0)
|
||||
get_all = true;
|
||||
else if (strncmp(key, "lxc.proc.", sizeof("lxc.proc.") - 1) == 0)
|
||||
key += sizeof("lxc.proc.") - 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
lxc_list_for_each(it, &c->procs) {
|
||||
struct lxc_proc *proc = it->elem;
|
||||
|
||||
if (get_all) {
|
||||
strprint(retv, inlen, "lxc.proc.%s = %s\n",
|
||||
proc->filename, proc->value);
|
||||
} else if (strcmp(proc->filename, key) == 0) {
|
||||
strprint(retv, inlen, "%s", proc->value);
|
||||
}
|
||||
}
|
||||
|
||||
return fulllen;
|
||||
}
|
||||
|
||||
static int get_config_noop(const char *key, char *retv, int inlen,
|
||||
struct lxc_conf *c, void *data)
|
||||
{
|
||||
@ -3797,6 +3882,12 @@ static inline int clr_config_sysctl(const char *key, struct lxc_conf *c,
|
||||
return lxc_clear_sysctls(c, key);
|
||||
}
|
||||
|
||||
static inline int clr_config_proc(const char *key, struct lxc_conf *c,
|
||||
void *data)
|
||||
{
|
||||
return lxc_clear_procs(c, key);
|
||||
}
|
||||
|
||||
static inline int clr_config_includefiles(const char *key, struct lxc_conf *c,
|
||||
void *data)
|
||||
{
|
||||
|
@ -1386,6 +1386,12 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
goto out_delete_net;
|
||||
}
|
||||
|
||||
if (!lxc_list_empty(&conf->procs)) {
|
||||
ret = setup_proc_filesystem(&conf->procs, handler->pid);
|
||||
if (ret < 0)
|
||||
goto out_delete_net;
|
||||
}
|
||||
|
||||
/* Tell the child to continue its initialization. We'll get
|
||||
* LXC_SYNC_CGROUP when it is ready for us to setup cgroups.
|
||||
*/
|
||||
|
@ -309,6 +309,73 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
printf("lxc.sysctl returned %d %s\n", ret, v3);
|
||||
|
||||
#define PROC_OOM_SCORE_ADJ "lxc.proc.oom_score_adj = 10\n"
|
||||
#define ALL_PROCS "lxc.proc.setgroups = allow\n" PROC_OOM_SCORE_ADJ
|
||||
|
||||
ret = c->get_config_item(c, "lxc.proc", v3, 2047);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.proc.setgroups", "allow")) {
|
||||
fprintf(stderr, "%d: failed to set lxc.proc.setgroups\n", __LINE__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = c->get_config_item(c, "lxc.proc.setgroups", v2, 255);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%d: get_config_item(lxc.proc.setgroups) returned %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(v2, "allow")) {
|
||||
fprintf(stderr, "%d: lxc.proc.setgroups returned wrong value: %d %s not 10\n", __LINE__, ret, v2);
|
||||
goto out;
|
||||
}
|
||||
printf("lxc.proc.setgroups returned %d %s\n", ret, v2);
|
||||
|
||||
if (!c->set_config_item(c, "lxc.proc.oom_score_adj", "10")) {
|
||||
fprintf(stderr, "%d: failed to set lxc.proc.oom_score_adj\n", __LINE__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = c->get_config_item(c, "lxc.proc.oom_score_adj", v2, 255);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%d: get_config_item(lxc.proc.oom_score_adj) returned %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(v2, "10")) {
|
||||
fprintf(stderr, "%d: lxc.proc.oom_score_adj returned wrong value: %d %s not 10\n", __LINE__, ret, v2);
|
||||
goto out;
|
||||
}
|
||||
printf("lxc.proc.oom_score_adj returned %d %s\n", ret, v2);
|
||||
|
||||
ret = c->get_config_item(c, "lxc.proc", v3, 2047);
|
||||
if (ret != sizeof(ALL_PROCS)-1) {
|
||||
fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(v3, ALL_PROCS)) {
|
||||
fprintf(stderr, "%d: lxc.proc returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(ALL_PROCS) - 1, ALL_PROCS);
|
||||
goto out;
|
||||
}
|
||||
printf("lxc.proc returned %d %s\n", ret, v3);
|
||||
|
||||
if (!c->clear_config_item(c, "lxc.proc.setgroups")) {
|
||||
fprintf(stderr, "%d: failed clearing lxc.proc.setgroups\n", __LINE__);
|
||||
goto out;
|
||||
}
|
||||
ret = c->get_config_item(c, "lxc.proc", v3, 2047);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(v3, PROC_OOM_SCORE_ADJ)) {
|
||||
fprintf(stderr, "%d: lxc.proc returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(PROC_OOM_SCORE_ADJ) - 1, PROC_OOM_SCORE_ADJ);
|
||||
goto out;
|
||||
}
|
||||
printf("lxc.proc returned %d %s\n", ret, v3);
|
||||
|
||||
if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) {
|
||||
fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__);
|
||||
goto out;
|
||||
|
@ -929,6 +929,13 @@ int main(int argc, char *argv[])
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
/* lxc.proc */
|
||||
if (set_get_compare_clear_save_load(c, "lxc.proc.oom_score_adj", "10", tmpf,
|
||||
true) < 0) {
|
||||
lxc_error("%s\n", "lxc.proc.oom_score_adj");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
/* REMOVE IN LXC 3.0
|
||||
legacy lxc.limit.* key
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user