]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc: add time namespace support
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 25 Jun 2020 12:39:29 +0000 (14:39 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 25 Jun 2020 23:03:24 +0000 (01:03 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/file_utils.c
src/lxc/file_utils.h
src/lxc/namespace.c
src/lxc/namespace.h
src/lxc/start.c
src/lxc/string_utils.c
src/lxc/string_utils.h

index 4aafca3cbb5f5c3fcb5a4a94883752f8563470ad..48cb74891f5f02d80b7bfa2d07f252badd395477 100644 (file)
@@ -2599,6 +2599,7 @@ struct lxc_conf *lxc_conf_init(void)
        new->init_gid = 0;
        memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
        memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX);
+       memset(&new->timens, 0, sizeof(struct timens_offsets));
        seccomp_conf_init(new);
 
        return new;
index b72afbaa569607200e1f2556571ebd1a6543a149..7f54539e0fd0ee8d71c1fcc6b70e57deb1f7b8ae 100644 (file)
@@ -233,6 +233,16 @@ struct device_item {
        int global_rule;
 };
 
+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 {
        /* Pointer to the name of the container. Do not free! */
        const char *name;
@@ -401,6 +411,8 @@ struct lxc_conf {
                /* Absolute path (in the container) to the shared mount point */
                char *path_cont;
        } shmount;
+
+       struct timens_offsets timens;
 };
 
 extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
index 68403e65e08c31b94d30c6a0a5c2dad9145227c5..c92e19820ddd55368bcca28ce381cda3425d9fb1 100644 (file)
@@ -104,6 +104,8 @@ lxc_config_define(mount_auto);
 lxc_config_define(mount_fstab);
 lxc_config_define(namespace_clone);
 lxc_config_define(namespace_keep);
+lxc_config_define(time_offset_boot);
+lxc_config_define(time_offset_monotonic);
 lxc_config_define(namespace_share);
 lxc_config_define(net);
 lxc_config_define(net_flags);
@@ -166,110 +168,112 @@ lxc_config_define(proc);
  * has to be placed above lxc.ab.
  */
 static struct lxc_config_t config_jump_table[] = {
-       { "lxc.arch",                      set_config_personality,                 get_config_personality,                 clr_config_personality,               },
-       { "lxc.apparmor.profile",          set_config_apparmor_profile,            get_config_apparmor_profile,            clr_config_apparmor_profile,          },
-       { "lxc.apparmor.allow_incomplete", set_config_apparmor_allow_incomplete,   get_config_apparmor_allow_incomplete,   clr_config_apparmor_allow_incomplete, },
-       { "lxc.apparmor.allow_nesting",    set_config_apparmor_allow_nesting,      get_config_apparmor_allow_nesting,      clr_config_apparmor_allow_nesting,    },
-       { "lxc.apparmor.raw",              set_config_apparmor_raw,                get_config_apparmor_raw,                clr_config_apparmor_raw,              },
-       { "lxc.autodev.tmpfs.size",        set_config_autodev_tmpfs_size,          get_config_autodev_tmpfs_size,          clr_config_autodev_tmpfs_size,        },
-       { "lxc.autodev",                   set_config_autodev,                     get_config_autodev,                     clr_config_autodev,                   },
-       { "lxc.cap.drop",                  set_config_cap_drop,                    get_config_cap_drop,                    clr_config_cap_drop,                  },
-       { "lxc.cap.keep",                  set_config_cap_keep,                    get_config_cap_keep,                    clr_config_cap_keep,                  },
-       { "lxc.cgroup2",                   set_config_cgroup2_controller,          get_config_cgroup2_controller,          clr_config_cgroup2_controller,        },
-       { "lxc.cgroup.dir.monitor",        set_config_cgroup_monitor_dir,          get_config_cgroup_monitor_dir,          clr_config_cgroup_monitor_dir,        },
-       { "lxc.cgroup.dir.container.inner",set_config_cgroup_container_inner_dir,  get_config_cgroup_container_inner_dir,  clr_config_cgroup_container_inner_dir,},
-       { "lxc.cgroup.dir.container",      set_config_cgroup_container_dir,        get_config_cgroup_container_dir,        clr_config_cgroup_container_dir,      },
-       { "lxc.cgroup.dir",                set_config_cgroup_dir,                  get_config_cgroup_dir,                  clr_config_cgroup_dir,                },
-       { "lxc.cgroup.relative",           set_config_cgroup_relative,             get_config_cgroup_relative,             clr_config_cgroup_relative,           },
-       { "lxc.cgroup",                    set_config_cgroup_controller,           get_config_cgroup_controller,           clr_config_cgroup_controller,         },
-       { "lxc.console.buffer.size",       set_config_console_buffer_size,         get_config_console_buffer_size,         clr_config_console_buffer_size,       },
-       { "lxc.console.logfile",           set_config_console_logfile,             get_config_console_logfile,             clr_config_console_logfile,           },
-       { "lxc.console.path",              set_config_console_path,                get_config_console_path,                clr_config_console_path,              },
-       { "lxc.console.rotate",            set_config_console_rotate,              get_config_console_rotate,              clr_config_console_rotate,            },
-       { "lxc.console.size",              set_config_console_size,                get_config_console_size,                clr_config_console_size,              },
-       { "lxc.environment",               set_config_environment,                 get_config_environment,                 clr_config_environment,               },
-       { "lxc.ephemeral",                 set_config_ephemeral,                   get_config_ephemeral,                   clr_config_ephemeral,                 },
-       { "lxc.execute.cmd",               set_config_execute_cmd,                 get_config_execute_cmd,                 clr_config_execute_cmd,               },
-       { "lxc.group",                     set_config_group,                       get_config_group,                       clr_config_group,                     },
-       { "lxc.hook.autodev",              set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.clone",                set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.destroy",              set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.mount",                set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.post-stop",            set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.pre-mount",            set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.pre-start",            set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.start",                set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.start-host",           set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.stop",                 set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.hook.version",              set_config_hooks_version,               get_config_hooks_version,               clr_config_hooks_version,             },
-       { "lxc.hook",                      set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-       { "lxc.idmap",                     set_config_idmaps,                      get_config_idmaps,                      clr_config_idmaps,                    },
-       { "lxc.include",                   set_config_includefiles,                get_config_includefiles,                clr_config_includefiles,              },
-       { "lxc.init.cmd",                  set_config_init_cmd,                    get_config_init_cmd,                    clr_config_init_cmd,                  },
-       { "lxc.init.gid",                  set_config_init_gid,                    get_config_init_gid,                    clr_config_init_gid,                  },
-       { "lxc.init.uid",                  set_config_init_uid,                    get_config_init_uid,                    clr_config_init_uid,                  },
-       { "lxc.init.cwd",                  set_config_init_cwd,                    get_config_init_cwd,                    clr_config_init_cwd,                  },
-       { "lxc.keyring.session",           set_config_keyring_session,             get_config_keyring_session,             clr_config_keyring_session            },
-       { "lxc.log.file",                  set_config_log_file,                    get_config_log_file,                    clr_config_log_file,                  },
-       { "lxc.log.level",                 set_config_log_level,                   get_config_log_level,                   clr_config_log_level,                 },
-       { "lxc.log.syslog",                set_config_log_syslog,                  get_config_log_syslog,                  clr_config_log_syslog,                },
-       { "lxc.monitor.unshare",           set_config_monitor,                     get_config_monitor,                     clr_config_monitor,                   },
-       { "lxc.monitor.signal.pdeath",     set_config_monitor_signal_pdeath,       get_config_monitor_signal_pdeath,       clr_config_monitor_signal_pdeath,     },
-       { "lxc.mount.auto",                set_config_mount_auto,                  get_config_mount_auto,                  clr_config_mount_auto,                },
-       { "lxc.mount.entry",               set_config_mount,                       get_config_mount,                       clr_config_mount,                     },
-       { "lxc.mount.fstab",               set_config_mount_fstab,                 get_config_mount_fstab,                 clr_config_mount_fstab,               },
-       { "lxc.namespace.clone",           set_config_namespace_clone,             get_config_namespace_clone,             clr_config_namespace_clone,           },
-       { "lxc.namespace.keep",            set_config_namespace_keep,              get_config_namespace_keep,              clr_config_namespace_keep,            },
-       { "lxc.namespace.share",           set_config_namespace_share,             get_config_namespace_share,             clr_config_namespace_share,           },
-       { "lxc.net.flags",                 set_config_net_flags,                   get_config_net_flags,                   clr_config_net_flags,                 },
-       { "lxc.net.hwaddr",                set_config_net_hwaddr,                  get_config_net_hwaddr,                  clr_config_net_hwaddr,                },
-       { "lxc.net.ipv4.address",          set_config_net_ipv4_address,            get_config_net_ipv4_address,            clr_config_net_ipv4_address,          },
-       { "lxc.net.ipv4.gateway",          set_config_net_ipv4_gateway,            get_config_net_ipv4_gateway,            clr_config_net_ipv4_gateway,          },
-       { "lxc.net.ipv6.address",          set_config_net_ipv6_address,            get_config_net_ipv6_address,            clr_config_net_ipv6_address,          },
-       { "lxc.net.ipv6.gateway",          set_config_net_ipv6_gateway,            get_config_net_ipv6_gateway,            clr_config_net_ipv6_gateway,          },
-       { "lxc.net.link",                  set_config_net_link,                    get_config_net_link,                    clr_config_net_link,                  },
-       { "lxc.net.l2proxy",               set_config_net_l2proxy,                 get_config_net_l2proxy,                 clr_config_net_l2proxy,               },
-       { "lxc.net.macvlan.mode",          set_config_net_macvlan_mode,            get_config_net_macvlan_mode,            clr_config_net_macvlan_mode,          },
-       { "lxc.net.ipvlan.mode",           set_config_net_ipvlan_mode,             get_config_net_ipvlan_mode,             clr_config_net_ipvlan_mode,           },
-       { "lxc.net.ipvlan.isolation",      set_config_net_ipvlan_isolation,        get_config_net_ipvlan_isolation,        clr_config_net_ipvlan_isolation,      },
-       { "lxc.net.mtu",                   set_config_net_mtu,                     get_config_net_mtu,                     clr_config_net_mtu,                   },
-       { "lxc.net.name",                  set_config_net_name,                    get_config_net_name,                    clr_config_net_name,                  },
-       { "lxc.net.script.down",           set_config_net_script_down,             get_config_net_script_down,             clr_config_net_script_down,           },
-       { "lxc.net.script.up",             set_config_net_script_up,               get_config_net_script_up,               clr_config_net_script_up,             },
-       { "lxc.net.type",                  set_config_net_type,                    get_config_net_type,                    clr_config_net_type,                  },
-       { "lxc.net.vlan.id",               set_config_net_vlan_id,                 get_config_net_vlan_id,                 clr_config_net_vlan_id,               },
-       { "lxc.net.veth.mode",             set_config_net_veth_mode,               get_config_net_veth_mode,               clr_config_net_veth_mode,             },
-       { "lxc.net.veth.pair",             set_config_net_veth_pair,               get_config_net_veth_pair,               clr_config_net_veth_pair,             },
-       { "lxc.net.veth.ipv4.route",       set_config_net_veth_ipv4_route,         get_config_net_veth_ipv4_route,         clr_config_net_veth_ipv4_route,       },
-       { "lxc.net.veth.ipv6.route",       set_config_net_veth_ipv6_route,         get_config_net_veth_ipv6_route,         clr_config_net_veth_ipv6_route,       },
-       { "lxc.net.veth.vlan.id",          set_config_net_veth_vlan_id,            get_config_net_veth_vlan_id,            clr_config_net_veth_vlan_id,          },
-       { "lxc.net.veth.vlan.tagged.id",   set_config_net_veth_vlan_tagged_id,     get_config_net_veth_vlan_tagged_id,     clr_config_net_veth_vlan_tagged_id,   },
-       { "lxc.net.",                      set_config_net_nic,                     get_config_net_nic,                     clr_config_net_nic,                   },
-       { "lxc.net",                       set_config_net,                         get_config_net,                         clr_config_net,                       },
-       { "lxc.no_new_privs",              set_config_no_new_privs,                get_config_no_new_privs,                clr_config_no_new_privs,              },
-       { "lxc.prlimit",                   set_config_prlimit,                     get_config_prlimit,                     clr_config_prlimit,                   },
-       { "lxc.pty.max",                   set_config_pty_max,                     get_config_pty_max,                     clr_config_pty_max,                   },
-       { "lxc.rootfs.managed",            set_config_rootfs_managed,              get_config_rootfs_managed,              clr_config_rootfs_managed,            },
-       { "lxc.rootfs.mount",              set_config_rootfs_mount,                get_config_rootfs_mount,                clr_config_rootfs_mount,              },
-       { "lxc.rootfs.options",            set_config_rootfs_options,              get_config_rootfs_options,              clr_config_rootfs_options,            },
-       { "lxc.rootfs.path",               set_config_rootfs_path,                 get_config_rootfs_path,                 clr_config_rootfs_path,               },
-       { "lxc.seccomp.allow_nesting",     set_config_seccomp_allow_nesting,       get_config_seccomp_allow_nesting,       clr_config_seccomp_allow_nesting,     },
-       { "lxc.seccomp.notify.cookie",     set_config_seccomp_notify_cookie,       get_config_seccomp_notify_cookie,       clr_config_seccomp_notify_cookie,     },
-       { "lxc.seccomp.notify.proxy",      set_config_seccomp_notify_proxy,        get_config_seccomp_notify_proxy,        clr_config_seccomp_notify_proxy,      },
-       { "lxc.seccomp.profile",           set_config_seccomp_profile,             get_config_seccomp_profile,             clr_config_seccomp_profile,           },
-       { "lxc.selinux.context.keyring",   set_config_selinux_context_keyring,     get_config_selinux_context_keyring,     clr_config_selinux_context_keyring    },
-       { "lxc.selinux.context",           set_config_selinux_context,             get_config_selinux_context,             clr_config_selinux_context,           },
-       { "lxc.signal.halt",               set_config_signal_halt,                 get_config_signal_halt,                 clr_config_signal_halt,               },
-       { "lxc.signal.reboot",             set_config_signal_reboot,               get_config_signal_reboot,               clr_config_signal_reboot,             },
-       { "lxc.signal.stop",               set_config_signal_stop,                 get_config_signal_stop,                 clr_config_signal_stop,               },
-       { "lxc.start.auto",                set_config_start,                       get_config_start,                       clr_config_start,                     },
-       { "lxc.start.delay",               set_config_start,                       get_config_start,                       clr_config_start,                     },
-       { "lxc.start.order",               set_config_start,                       get_config_start,                       clr_config_start,                     },
-       { "lxc.tty.dir",                   set_config_tty_dir,                     get_config_tty_dir,                     clr_config_tty_dir,                   },
-       { "lxc.tty.max",                   set_config_tty_max,                     get_config_tty_max,                     clr_config_tty_max,                   },
-       { "lxc.uts.name",                  set_config_uts_name,                    get_config_uts_name,                    clr_config_uts_name,                  },
-       { "lxc.sysctl",                    set_config_sysctl,                      get_config_sysctl,                      clr_config_sysctl,                    },
-       { "lxc.proc",                      set_config_proc,                        get_config_proc,                        clr_config_proc,                      },
+       { "lxc.arch",                       set_config_personality,                get_config_personality,                clr_config_personality,                },
+       { "lxc.apparmor.profile",           set_config_apparmor_profile,           get_config_apparmor_profile,           clr_config_apparmor_profile,           },
+       { "lxc.apparmor.allow_incomplete",  set_config_apparmor_allow_incomplete,  get_config_apparmor_allow_incomplete,  clr_config_apparmor_allow_incomplete,  },
+       { "lxc.apparmor.allow_nesting",     set_config_apparmor_allow_nesting,     get_config_apparmor_allow_nesting,     clr_config_apparmor_allow_nesting,     },
+       { "lxc.apparmor.raw",               set_config_apparmor_raw,               get_config_apparmor_raw,               clr_config_apparmor_raw,               },
+       { "lxc.autodev.tmpfs.size",         set_config_autodev_tmpfs_size,         get_config_autodev_tmpfs_size,         clr_config_autodev_tmpfs_size,         },
+       { "lxc.autodev",                    set_config_autodev,                    get_config_autodev,                    clr_config_autodev,                    },
+       { "lxc.cap.drop",                   set_config_cap_drop,                   get_config_cap_drop,                   clr_config_cap_drop,                   },
+       { "lxc.cap.keep",                   set_config_cap_keep,                   get_config_cap_keep,                   clr_config_cap_keep,                   },
+       { "lxc.cgroup2",                    set_config_cgroup2_controller,         get_config_cgroup2_controller,         clr_config_cgroup2_controller,         },
+       { "lxc.cgroup.dir.monitor",         set_config_cgroup_monitor_dir,         get_config_cgroup_monitor_dir,         clr_config_cgroup_monitor_dir,         },
+       { "lxc.cgroup.dir.container.inner", set_config_cgroup_container_inner_dir, get_config_cgroup_container_inner_dir, clr_config_cgroup_container_inner_dir, },
+       { "lxc.cgroup.dir.container",       set_config_cgroup_container_dir,       get_config_cgroup_container_dir,       clr_config_cgroup_container_dir,       },
+       { "lxc.cgroup.dir",                 set_config_cgroup_dir,                 get_config_cgroup_dir,                 clr_config_cgroup_dir,                 },
+       { "lxc.cgroup.relative",            set_config_cgroup_relative,            get_config_cgroup_relative,            clr_config_cgroup_relative,            },
+       { "lxc.cgroup",                     set_config_cgroup_controller,          get_config_cgroup_controller,          clr_config_cgroup_controller,          },
+       { "lxc.console.buffer.size",        set_config_console_buffer_size,        get_config_console_buffer_size,        clr_config_console_buffer_size,        },
+       { "lxc.console.logfile",            set_config_console_logfile,            get_config_console_logfile,            clr_config_console_logfile,            },
+       { "lxc.console.path",               set_config_console_path,               get_config_console_path,               clr_config_console_path,               },
+       { "lxc.console.rotate",             set_config_console_rotate,             get_config_console_rotate,             clr_config_console_rotate,             },
+       { "lxc.console.size",               set_config_console_size,               get_config_console_size,               clr_config_console_size,               },
+       { "lxc.environment",                set_config_environment,                get_config_environment,                clr_config_environment,                },
+       { "lxc.ephemeral",                  set_config_ephemeral,                  get_config_ephemeral,                  clr_config_ephemeral,                  },
+       { "lxc.execute.cmd",                set_config_execute_cmd,                get_config_execute_cmd,                clr_config_execute_cmd,                },
+       { "lxc.group",                      set_config_group,                      get_config_group,                      clr_config_group,                      },
+       { "lxc.hook.autodev",               set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.clone",                 set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.destroy",               set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.mount",                 set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.post-stop",             set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.pre-mount",             set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.pre-start",             set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.start",                 set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.start-host",            set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.stop",                  set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.hook.version",               set_config_hooks_version,              get_config_hooks_version,              clr_config_hooks_version,              },
+       { "lxc.hook",                       set_config_hooks,                      get_config_hooks,                      clr_config_hooks,                      },
+       { "lxc.idmap",                      set_config_idmaps,                     get_config_idmaps,                     clr_config_idmaps,                     },
+       { "lxc.include",                    set_config_includefiles,               get_config_includefiles,               clr_config_includefiles,               },
+       { "lxc.init.cmd",                   set_config_init_cmd,                   get_config_init_cmd,                   clr_config_init_cmd,                   },
+       { "lxc.init.gid",                   set_config_init_gid,                   get_config_init_gid,                   clr_config_init_gid,                   },
+       { "lxc.init.uid",                   set_config_init_uid,                   get_config_init_uid,                   clr_config_init_uid,                   },
+       { "lxc.init.cwd",                   set_config_init_cwd,                   get_config_init_cwd,                   clr_config_init_cwd,                   },
+       { "lxc.keyring.session",            set_config_keyring_session,            get_config_keyring_session,            clr_config_keyring_session             },
+       { "lxc.log.file",                   set_config_log_file,                   get_config_log_file,                   clr_config_log_file,                   },
+       { "lxc.log.level",                  set_config_log_level,                  get_config_log_level,                  clr_config_log_level,                  },
+       { "lxc.log.syslog",                 set_config_log_syslog,                 get_config_log_syslog,                 clr_config_log_syslog,                 },
+       { "lxc.monitor.unshare",            set_config_monitor,                    get_config_monitor,                    clr_config_monitor,                    },
+       { "lxc.monitor.signal.pdeath",      set_config_monitor_signal_pdeath,      get_config_monitor_signal_pdeath,      clr_config_monitor_signal_pdeath,      },
+       { "lxc.mount.auto",                 set_config_mount_auto,                 get_config_mount_auto,                 clr_config_mount_auto,                 },
+       { "lxc.mount.entry",                set_config_mount,                      get_config_mount,                      clr_config_mount,                      },
+       { "lxc.mount.fstab",                set_config_mount_fstab,                get_config_mount_fstab,                clr_config_mount_fstab,                },
+       { "lxc.namespace.clone",            set_config_namespace_clone,            get_config_namespace_clone,            clr_config_namespace_clone,            },
+       { "lxc.namespace.keep",             set_config_namespace_keep,             get_config_namespace_keep,             clr_config_namespace_keep,             },
+       { "lxc.namespace.share",            set_config_namespace_share,            get_config_namespace_share,            clr_config_namespace_share,            },
+       { "lxc.time.offset.boot",           set_config_time_offset_boot,           get_config_time_offset_boot,           clr_config_time_offset_boot,           },
+       { "lxc.time.offset.monotonic",      set_config_time_offset_monotonic,      get_config_time_offset_monotonic,      clr_config_time_offset_monotonic,      },
+       { "lxc.net.flags",                  set_config_net_flags,                  get_config_net_flags,                  clr_config_net_flags,                  },
+       { "lxc.net.hwaddr",                 set_config_net_hwaddr,                 get_config_net_hwaddr,                 clr_config_net_hwaddr,                 },
+       { "lxc.net.ipv4.address",           set_config_net_ipv4_address,           get_config_net_ipv4_address,           clr_config_net_ipv4_address,           },
+       { "lxc.net.ipv4.gateway",           set_config_net_ipv4_gateway,           get_config_net_ipv4_gateway,           clr_config_net_ipv4_gateway,           },
+       { "lxc.net.ipv6.address",           set_config_net_ipv6_address,           get_config_net_ipv6_address,           clr_config_net_ipv6_address,           },
+       { "lxc.net.ipv6.gateway",           set_config_net_ipv6_gateway,           get_config_net_ipv6_gateway,           clr_config_net_ipv6_gateway,           },
+       { "lxc.net.link",                   set_config_net_link,                   get_config_net_link,                   clr_config_net_link,                   },
+       { "lxc.net.l2proxy",                set_config_net_l2proxy,                get_config_net_l2proxy,                clr_config_net_l2proxy,                },
+       { "lxc.net.macvlan.mode",           set_config_net_macvlan_mode,           get_config_net_macvlan_mode,           clr_config_net_macvlan_mode,           },
+       { "lxc.net.ipvlan.mode",            set_config_net_ipvlan_mode,            get_config_net_ipvlan_mode,            clr_config_net_ipvlan_mode,            },
+       { "lxc.net.ipvlan.isolation",       set_config_net_ipvlan_isolation,       get_config_net_ipvlan_isolation,       clr_config_net_ipvlan_isolation,       },
+       { "lxc.net.mtu",                    set_config_net_mtu,                    get_config_net_mtu,                    clr_config_net_mtu,                    },
+       { "lxc.net.name",                   set_config_net_name,                   get_config_net_name,                   clr_config_net_name,                   },
+       { "lxc.net.script.down",            set_config_net_script_down,            get_config_net_script_down,            clr_config_net_script_down,            },
+       { "lxc.net.script.up",              set_config_net_script_up,              get_config_net_script_up,              clr_config_net_script_up,              },
+       { "lxc.net.type",                   set_config_net_type,                   get_config_net_type,                   clr_config_net_type,                   },
+       { "lxc.net.vlan.id",                set_config_net_vlan_id,                get_config_net_vlan_id,                clr_config_net_vlan_id,                },
+       { "lxc.net.veth.mode",              set_config_net_veth_mode,              get_config_net_veth_mode,              clr_config_net_veth_mode,              },
+       { "lxc.net.veth.pair",              set_config_net_veth_pair,              get_config_net_veth_pair,              clr_config_net_veth_pair,              },
+       { "lxc.net.veth.ipv4.route",        set_config_net_veth_ipv4_route,        get_config_net_veth_ipv4_route,        clr_config_net_veth_ipv4_route,        },
+       { "lxc.net.veth.ipv6.route",        set_config_net_veth_ipv6_route,        get_config_net_veth_ipv6_route,        clr_config_net_veth_ipv6_route,        },
+       { "lxc.net.veth.vlan.id",           set_config_net_veth_vlan_id,           get_config_net_veth_vlan_id,           clr_config_net_veth_vlan_id,           },
+       { "lxc.net.veth.vlan.tagged.id",    set_config_net_veth_vlan_tagged_id,    get_config_net_veth_vlan_tagged_id,    clr_config_net_veth_vlan_tagged_id,    },
+       { "lxc.net.",                       set_config_net_nic,                    get_config_net_nic,                    clr_config_net_nic,                    },
+       { "lxc.net",                        set_config_net,                        get_config_net,                        clr_config_net,                        },
+       { "lxc.no_new_privs",               set_config_no_new_privs,               get_config_no_new_privs,               clr_config_no_new_privs,               },
+       { "lxc.prlimit",                    set_config_prlimit,                    get_config_prlimit,                    clr_config_prlimit,                    },
+       { "lxc.pty.max",                    set_config_pty_max,                    get_config_pty_max,                    clr_config_pty_max,                    },
+       { "lxc.rootfs.managed",             set_config_rootfs_managed,             get_config_rootfs_managed,             clr_config_rootfs_managed,             },
+       { "lxc.rootfs.mount",               set_config_rootfs_mount,               get_config_rootfs_mount,               clr_config_rootfs_mount,               },
+       { "lxc.rootfs.options",             set_config_rootfs_options,             get_config_rootfs_options,             clr_config_rootfs_options,             },
+       { "lxc.rootfs.path",                set_config_rootfs_path,                get_config_rootfs_path,                clr_config_rootfs_path,                },
+       { "lxc.seccomp.allow_nesting",      set_config_seccomp_allow_nesting,      get_config_seccomp_allow_nesting,      clr_config_seccomp_allow_nesting,      },
+       { "lxc.seccomp.notify.cookie",      set_config_seccomp_notify_cookie,      get_config_seccomp_notify_cookie,      clr_config_seccomp_notify_cookie,      },
+       { "lxc.seccomp.notify.proxy",       set_config_seccomp_notify_proxy,       get_config_seccomp_notify_proxy,       clr_config_seccomp_notify_proxy,       },
+       { "lxc.seccomp.profile",            set_config_seccomp_profile,            get_config_seccomp_profile,            clr_config_seccomp_profile,            },
+       { "lxc.selinux.context.keyring",    set_config_selinux_context_keyring,    get_config_selinux_context_keyring,    clr_config_selinux_context_keyring     },
+       { "lxc.selinux.context",            set_config_selinux_context,            get_config_selinux_context,            clr_config_selinux_context,            },
+       { "lxc.signal.halt",                set_config_signal_halt,                get_config_signal_halt,                clr_config_signal_halt,                },
+       { "lxc.signal.reboot",              set_config_signal_reboot,              get_config_signal_reboot,              clr_config_signal_reboot,              },
+       { "lxc.signal.stop",                set_config_signal_stop,                get_config_signal_stop,                clr_config_signal_stop,                },
+       { "lxc.start.auto",                 set_config_start,                      get_config_start,                      clr_config_start,                      },
+       { "lxc.start.delay",                set_config_start,                      get_config_start,                      clr_config_start,                      },
+       { "lxc.start.order",                set_config_start,                      get_config_start,                      clr_config_start,                      },
+       { "lxc.tty.dir",                    set_config_tty_dir,                    get_config_tty_dir,                    clr_config_tty_dir,                    },
+       { "lxc.tty.max",                    set_config_tty_max,                    get_config_tty_max,                    clr_config_tty_max,                    },
+       { "lxc.uts.name",                   set_config_uts_name,                   get_config_uts_name,                   clr_config_uts_name,                   },
+       { "lxc.sysctl",                     set_config_sysctl,                     get_config_sysctl,                     clr_config_sysctl,                     },
+       { "lxc.proc",                       set_config_proc,                       get_config_proc,                       clr_config_proc,                       },
 };
 
 static const size_t config_jump_table_size = sizeof(config_jump_table) / sizeof(struct lxc_config_t);
@@ -2812,6 +2816,76 @@ static int set_config_namespace_keep(const char *key, const char *value,
        return 0;
 }
 
+static int set_config_time_offset_boot(const char *key, const char *value,
+                                      struct lxc_conf *lxc_conf, void *data)
+{
+       int ret;
+       char *unit;
+       int64_t offset = 0;
+       char buf[STRLITERALLEN("ms") + 1];
+
+       if (lxc_config_value_empty(value))
+               return clr_config_time_offset_boot(key, lxc_conf, data);
+
+       ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+       if (ret)
+               return ret;
+
+       /* TODO: Handle overflow. */
+       unit = lxc_trim_whitespace_in_place(buf);
+       if (strcmp(unit, "h") == 0)
+               lxc_conf->timens.s_boot = offset * 3600;
+       else if (strcmp(unit, "m") == 0)
+               lxc_conf->timens.s_boot = offset * 60;
+       else if (strcmp(unit, "s") == 0)
+               lxc_conf->timens.s_boot = offset;
+       else if (strcmp(unit, "ms") == 0)
+               lxc_conf->timens.ns_boot = offset * 1000000;
+       else if (strcmp(unit, "us") == 0)
+               lxc_conf->timens.ns_boot = offset * 1000;
+       else if (strcmp(unit, "ns") == 0)
+               lxc_conf->timens.ns_boot = offset;
+       else
+               return ret_errno(EINVAL);
+
+       return 0;
+}
+
+static int set_config_time_offset_monotonic(const char *key, const char *value,
+                                           struct lxc_conf *lxc_conf, void *data)
+{
+       int ret;
+       char *unit;
+       int64_t offset = 0;
+       char buf[STRLITERALLEN("ms") + 1];
+
+       if (lxc_config_value_empty(value))
+               return clr_config_time_offset_monotonic(key, lxc_conf, data);
+
+       ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+       if (ret)
+               return ret;
+
+       // TODO: Handle overflow.
+       unit = lxc_trim_whitespace_in_place(buf);
+       if (strcmp(unit, "h") == 0)
+               lxc_conf->timens.s_monotonic = offset * 3600;
+       else if (strcmp(unit, "m") == 0)
+               lxc_conf->timens.s_monotonic = offset * 60;
+       else if (strcmp(unit, "s") == 0)
+               lxc_conf->timens.s_monotonic = offset;
+       else if (strcmp(unit, "ms") == 0)
+               lxc_conf->timens.ns_monotonic = offset * 1000000;
+       else if (strcmp(unit, "us") == 0)
+               lxc_conf->timens.ns_monotonic = offset * 1000;
+       else if (strcmp(unit, "ns") == 0)
+               lxc_conf->timens.ns_monotonic = offset;
+       else
+               return ret_errno(EINVAL);
+
+       return 0;
+}
+
 static int set_config_namespace_share(const char *key, const char *value,
                                      struct lxc_conf *lxc_conf, void *data)
 {
@@ -4497,6 +4571,46 @@ static int get_config_namespace_keep(const char *key, char *retv, int inlen,
        return fulllen;
 }
 
+static int get_config_time_offset_boot(const char *key, char *retv, int inlen, struct lxc_conf *c,
+                                      void *data)
+{
+       int len;
+       int fulllen = 0;
+
+       if (!retv)
+               inlen = 0;
+       else
+               memset(retv, 0, inlen);
+
+       if (c->timens.s_boot) {
+               strprint(retv, inlen, "%" PRId64 " s\n", c->timens.s_boot);
+       } else {
+               strprint(retv, inlen, "%" PRId64 " ns\n", c->timens.ns_boot);
+       }
+
+       return fulllen;
+}
+
+static int get_config_time_offset_monotonic(const char *key, char *retv, int inlen,
+                                           struct lxc_conf *c, void *data)
+{
+       int len;
+       int fulllen = 0;
+
+       if (!retv)
+               inlen = 0;
+       else
+               memset(retv, 0, inlen);
+
+       if (c->timens.s_monotonic) {
+               strprint(retv, inlen, "%" PRId64 "s\n", c->timens.s_monotonic);
+       } else {
+               strprint(retv, inlen, "%" PRId64 "ns\n", c->timens.ns_monotonic);
+       }
+
+       return fulllen;
+}
+
 static int get_config_namespace_share(const char *key, char *retv, int inlen,
                                      struct lxc_conf *c, void *data)
 {
@@ -5030,6 +5144,20 @@ static int clr_config_namespace_keep(const char *key, struct lxc_conf *lxc_conf,
        return 0;
 }
 
+static int clr_config_time_offset_boot(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+       lxc_conf->timens.s_boot = 0;
+       lxc_conf->timens.ns_boot = 0;
+       return 0;
+}
+
+static int clr_config_time_offset_monotonic(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+       lxc_conf->timens.s_monotonic = 0;
+       lxc_conf->timens.ns_monotonic = 0;
+       return 0;
+}
+
 static int clr_config_namespace_share(const char *key,
                                      struct lxc_conf *lxc_conf, void *data)
 {
index 1689cbaa7f90d360b39216a51bcc777947da2f60..85e24fea20a7f1611e9e06f3c4d9bb67fbca3dd2 100644 (file)
@@ -512,3 +512,30 @@ FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer)
 #endif
        return f;
 }
+
+int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset)
+{
+       __do_close int fd = -EBADF;
+       int ret;
+       ssize_t len;
+       char buf[INTTYPE_TO_STRLEN(int) +
+                STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) +
+                STRLITERALLEN(" ") + INTTYPE_TO_STRLEN(int64_t) + 1];
+
+       if (clk_id == CLOCK_MONOTONIC_COARSE || clk_id == CLOCK_MONOTONIC_RAW)
+               clk_id = CLOCK_MONOTONIC;
+
+       fd = open("/proc/self/timens_offsets", O_WRONLY | O_CLOEXEC);
+       if (fd < 0)
+               return -errno;
+
+       len = snprintf(buf, sizeof(buf), "%d %" PRId64 " %" PRId64, clk_id, s_offset, ns_offset);
+       if (len < 0 || len >= sizeof(buf))
+               return ret_errno(EFBIG);
+
+       ret = lxc_write_nointr(fd, buf, len);
+       if (ret < 0 || (size_t)ret != len)
+               return -EIO;
+
+       return 0;
+}
index f9c8abe0335246bbc697dc2adb2821623476d312..6f11ec9d7ad0e3fba0ddcbeca1fbd5fb5acd29a0 100644 (file)
@@ -82,5 +82,6 @@ extern int lxc_open_dirfd(const char *dir);
 extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer);
 extern FILE *fopen_cached(const char *path, const char *mode,
                          void **caller_freed_buffer);
+extern int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset);
 
 #endif /* __LXC_FILE_UTILS_H */
index f2e01756303c30db6a980ca364fb696f13defc27..a46923078d8add3fec4dabe5a9b3ba32ad547a6a 100644 (file)
@@ -44,7 +44,8 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
        [LXC_NS_UTS]    =  { "uts",    CLONE_NEWUTS,    "CLONE_NEWUTS",    "LXC_UTS_NS"     },
        [LXC_NS_IPC]    =  { "ipc",    CLONE_NEWIPC,    "CLONE_NEWIPC",    "LXC_IPC_NS"     },
        [LXC_NS_NET]    =  { "net",    CLONE_NEWNET,    "CLONE_NEWNET",    "LXC_NET_NS"     },
-       [LXC_NS_CGROUP] =  { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS"  }
+       [LXC_NS_CGROUP] =  { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS"  },
+       [LXC_NS_TIME]   =  { "time",   CLONE_NEWTIME,   "CLONE_NEWTIME",   "LXC_TIME_NS"    },
 };
 
 int lxc_namespace_2_cloneflag(const char *namespace)
index 84976f60f29247cace426ae217506b25ba8e502b..59b26fa60d6056b7e32ccdb7e58df57c777ccf08 100644 (file)
@@ -15,6 +15,7 @@ enum {
        LXC_NS_IPC,
        LXC_NS_NET,
        LXC_NS_CGROUP,
+       LXC_NS_TIME,
        LXC_NS_MAX
 };
 
index fd969c4332c26a9ffaf141ae32111f8c8d510472..16e519e993f0a9c110ec44c0419ba6d859c784c1 100644 (file)
@@ -1205,6 +1205,55 @@ static int do_start(void *data)
                }
        }
 
+       if (handler->ns_clone_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
         * allow them to be used by the various hooks, such as the start hook
         * below.
@@ -1452,6 +1501,8 @@ int resolve_clone_flags(struct lxc_handler *handler)
 {
        int i;
        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++) {
                if (conf->ns_keep) {
@@ -1470,6 +1521,9 @@ int resolve_clone_flags(struct lxc_handler *handler)
                        if (i == LXC_NS_CGROUP && !cgns_supported())
                                continue;
 
+                       if (i == LXC_NS_TIME && !wants_timens)
+                               continue;
+
                        handler->ns_clone_flags |= ns_info[i].clone_flag;
                }
 
@@ -1480,6 +1534,9 @@ int resolve_clone_flags(struct lxc_handler *handler)
                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");
+
        return 0;
 }
 
@@ -1614,6 +1671,9 @@ static int lxc_spawn(struct lxc_handler *handler)
        /* The cgroup namespace gets unshare()ed not clone()ed. */
        handler->ns_on_clone_flags &= ~CLONE_NEWCGROUP;
 
+       /* The time namespace (currently) gets unshare()ed not clone()ed. */
+       handler->ns_on_clone_flags &= ~CLONE_NEWTIME;
+
        if (share_ns) {
                pid_t attacher_pid;
 
index dcb1160e4cc58247a77a0332352866c7761d2681..3d0d31a6c6e9f75ee1a9346c95454f041954ccca 100644 (file)
@@ -667,6 +667,51 @@ int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base)
        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)
 {
        char *err = NULL;
index 0f7d2ff21e0c88d72d2c4e28ac16b322165dc6b8..2ce3774423bdadaf5433fdd453d5dfc5c6281ac2 100644 (file)
@@ -76,6 +76,8 @@ extern int lxc_safe_long(const char *numstr, long int *converted);
 extern int lxc_safe_long_long(const char *numstr, long long int *converted);
 extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
 extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base);
+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. */
 extern int parse_byte_size_string(const char *s, int64_t *converted);