]> git.proxmox.com Git - mirror_lxc.git/commitdiff
confile: add lxc.proc.* to set proc filesystem
authorYifeng Tan <tanyifeng1@huawei.com>
Thu, 7 Dec 2017 18:00:47 +0000 (02:00 +0800)
committerYifeng Tan <tanyifeng1@huawei.com>
Wed, 13 Dec 2017 12:08:56 +0000 (20:08 +0800)
Signed-off-by: Yifeng Tan <tanyifeng1@huawei.com>
doc/lxc.container.conf.sgml.in
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/start.c
src/tests/get_item.c
src/tests/parse_config_file.c

index 7a6dd484106ddade8a9d2f21e05c4b3156f8640a..ed8bef7e193cda45a0abefc182760b844e2b5797 100644 (file)
@@ -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>
index 6a452064b74799ac32298f3ff8a0d52e6627b920..64d02d845bfcf080cfda9f45831de0291952fac4 100644 (file)
@@ -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);
index e60a6151ff4a6b4f4a1bb2c5a444e9367ec1c35e..0cf04a53f220c37886ecbf28476bc1368d16e1f7 100644 (file)
@@ -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 */
index 584f93630c5f633ab7f858337357c81e185ba2b5..47424b4f264726cd1a1977195c646b9c40c2f3bc 100644 (file)
@@ -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)
 {
index a8acfea17164464fb088afc4aedd3fd40ac1a6da..c301d7f0b81450b411a02d2a8424c3961a02f2b2 100644 (file)
@@ -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.
         */
index 7a15c1c891cfa8ce0399d38b6c8879bf4d9658ce..c2c561235c3b00cc99717e6bf464309513d40879 100644 (file)
@@ -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;
index 556d6d034a75e200c70ba8253a2b8e77452a3523..f6fda5a05d47ed52930b10a44f5a9a11b0011096 100644 (file)
@@ -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
         */