Skip to content

Commit

Permalink
Support time namespace
Browse files Browse the repository at this point in the history
"time" namespace was introduced in Linux v5.6
support new time namespace to set boottime and monotonic time offset

Example runtime spec

"timeOffsets": {
    "monotonic": {
        "secs": 172800,
        "nanosecs": 0
    },
    "boottime": {
        "secs": 604800,
        "nanosecs": 0
    }
}

Signed-off-by: Chethan Suresh <chethan.suresh@sony.com>
  • Loading branch information
chethanah committed Aug 3, 2023
1 parent dbe8434 commit d29ead9
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libcontainer/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ type Config struct {
// Do not try to remount a bind mount again after the first attempt failed on source
// filesystems that have nodev, noexec, nosuid, noatime, relatime, strictatime, nodiratime set
NoMountFallback bool `json:"no_mount_fallback,omitempty"`

// TimeOffsets specifies the offset for supporting time namespaces.
TimeOffsets map[string]specs.LinuxTimeOffset `json:"time_offsets,omitempty"`
}

type (
Expand Down
4 changes: 4 additions & 0 deletions libcontainer/configs/namespaces_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const (
NEWIPC NamespaceType = "NEWIPC"
NEWUSER NamespaceType = "NEWUSER"
NEWCGROUP NamespaceType = "NEWCGROUP"
NEWTIME NamespaceType = "NEWTIME"
)

var (
Expand All @@ -38,6 +39,8 @@ func NsName(ns NamespaceType) string {
return "uts"
case NEWCGROUP:
return "cgroup"
case NEWTIME:
return "time"
}
return ""
}
Expand Down Expand Up @@ -72,6 +75,7 @@ func NamespaceTypes() []NamespaceType {
NEWPID,
NEWNS,
NEWCGROUP,
NEWTIME,
}
}

Expand Down
1 change: 1 addition & 0 deletions libcontainer/configs/namespaces_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var namespaceInfo = map[NamespaceType]int{
NEWUTS: unix.CLONE_NEWUTS,
NEWPID: unix.CLONE_NEWPID,
NEWCGROUP: unix.CLONE_NEWCGROUP,
NEWTIME: unix.CLONE_NEWTIME,
}

// CloneFlags parses the container's Namespaces options to set the correct
Expand Down
6 changes: 6 additions & 0 deletions libcontainer/configs/validate/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ func namespaces(config *configs.Config) error {
}
}

if config.Namespaces.Contains(configs.NEWTIME) {
if _, err := os.Stat("/proc/self/timens_offsets"); os.IsNotExist(err) {
return errors.New("time namespaces aren't enabled in the kernel")
}
}

return nil
}

Expand Down
12 changes: 12 additions & 0 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,18 @@ func (c *Container) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Namespa
})
}

// write boottime and monotonic time ns offsets.
if c.config.Namespaces.Contains(configs.NEWTIME) && c.config.TimeOffsets != nil {
var offsetSpec bytes.Buffer
for clock, offset := range c.config.TimeOffsets {
fmt.Fprintf(&offsetSpec, "%s %d %d\n", clock, offset.Secs, offset.Nanosecs)
}
r.AddData(&Bytemsg{
Type: TimeOffsetsAttr,
Value: offsetSpec.Bytes(),
})
}

return bytes.NewReader(r.Serialize()), nil
}

Expand Down
1 change: 1 addition & 0 deletions libcontainer/message_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
GidmapPathAttr uint16 = 27289
MountSourcesAttr uint16 = 27290
IdmapSourcesAttr uint16 = 27291
TimeOffsetsAttr uint16 = 27292
)

type Int32msg struct {
Expand Down
3 changes: 3 additions & 0 deletions libcontainer/nsenter/namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000 /* New network namespace */
#endif
#ifndef CLONE_NEWTIME
# define CLONE_NEWTIME 0x00000080 /* New time namespace */
#endif

#endif /* NSENTER_NAMESPACE_H */
26 changes: 26 additions & 0 deletions libcontainer/nsenter/nsexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ struct nlconfig_t {
/* Idmap sources opened outside the container userns which will be id mapped. */
char *idmapsources;
size_t idmapsources_len;

/* Time NS offsets. */
char *timensoffset;
size_t timensoffset_len;
};

/*
Expand All @@ -122,6 +126,7 @@ struct nlconfig_t {
#define GIDMAPPATH_ATTR 27289
#define MOUNT_SOURCES_ATTR 27290
#define IDMAP_SOURCES_ATTR 27291
#define TIMENSOFFSET_ATTR 27292

/*
* Use the raw syscall for versions of glibc which don't include a function for
Expand Down Expand Up @@ -351,6 +356,8 @@ static int nsflag(char *name)
return CLONE_NEWUSER;
else if (!strcmp(name, "uts"))
return CLONE_NEWUTS;
else if (!strcmp(name, "time"))
return CLONE_NEWTIME;

/* If we don't recognise a name, fallback to 0. */
return 0;
Expand Down Expand Up @@ -444,6 +451,9 @@ static void nl_parse(int fd, struct nlconfig_t *config)
case IDMAP_SOURCES_ATTR:
config->idmapsources = current;
config->idmapsources_len = payload_len;
case TIMENSOFFSET_ATTR:
config->timensoffset = current;
config->timensoffset_len = payload_len;
break;
default:
bail("unknown netlink message type %d", nlattr->nla_type);
Expand Down Expand Up @@ -747,6 +757,17 @@ void receive_idmapsources(int sockfd)
receive_fd_sources(sockfd, "_LIBCONTAINER_IDMAP_FDS");
}

static void update_timens(char *map, size_t map_len)
{
if (map == NULL || map_len == 0)
return;
write_log(DEBUG, "update /proc/self/timens_offsets to '%s'", map);
if (write_file(map, map_len, "/proc/self/timens_offsets") < 0) {
if (errno != EPERM)
bail("failed to update /proc/self/timens_offsets");
}
}

void nsexec(void)
{
int pipenum;
Expand Down Expand Up @@ -1185,6 +1206,11 @@ void nsexec(void)
bail("failed to sync with parent: SYNC_MOUNT_IDMAP_ACK: got %u", s);
}

/*
* set boottime and monotonic timens offsets.
*/
update_timens(config.timensoffset, config.timensoffset_len);

/*
* TODO: What about non-namespace clone flags that we're dropping here?
*
Expand Down
4 changes: 4 additions & 0 deletions libcontainer/specconv/spec_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func initMaps() {
specs.IPCNamespace: configs.NEWIPC,
specs.UTSNamespace: configs.NEWUTS,
specs.CgroupNamespace: configs.NEWCGROUP,
specs.TimeNamespace: configs.NEWTIME,
}

mountPropagationMapping = map[string]int{
Expand Down Expand Up @@ -435,6 +436,9 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
MemBwSchema: spec.Linux.IntelRdt.MemBwSchema,
}
}

// update timens offsets
config.TimeOffsets = spec.Linux.TimeOffsets
}

// Set the host UID that should own the container's cgroup.
Expand Down

0 comments on commit d29ead9

Please sign in to comment.