Skip to content

Commit 0866112

Browse files
committed
merge #3876 into opencontainers/runc:main
Chethan Suresh (1): Support time namespace LGTMs: kolyskin cyphar Closes #3876
2 parents cb44958 + ebc2e7c commit 0866112

File tree

9 files changed

+61
-0
lines changed

9 files changed

+61
-0
lines changed

libcontainer/configs/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ type Config struct {
216216
// Do not try to remount a bind mount again after the first attempt failed on source
217217
// filesystems that have nodev, noexec, nosuid, noatime, relatime, strictatime, nodiratime set
218218
NoMountFallback bool `json:"no_mount_fallback,omitempty"`
219+
220+
// TimeOffsets specifies the offset for supporting time namespaces.
221+
TimeOffsets map[string]specs.LinuxTimeOffset `json:"time_offsets,omitempty"`
219222
}
220223

221224
type (

libcontainer/configs/namespaces_linux.go

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const (
1414
NEWIPC NamespaceType = "NEWIPC"
1515
NEWUSER NamespaceType = "NEWUSER"
1616
NEWCGROUP NamespaceType = "NEWCGROUP"
17+
NEWTIME NamespaceType = "NEWTIME"
1718
)
1819

1920
var (
@@ -38,6 +39,8 @@ func NsName(ns NamespaceType) string {
3839
return "uts"
3940
case NEWCGROUP:
4041
return "cgroup"
42+
case NEWTIME:
43+
return "time"
4144
}
4245
return ""
4346
}
@@ -72,6 +75,7 @@ func NamespaceTypes() []NamespaceType {
7275
NEWPID,
7376
NEWNS,
7477
NEWCGROUP,
78+
NEWTIME,
7579
}
7680
}
7781

libcontainer/configs/namespaces_syscall.go

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var namespaceInfo = map[NamespaceType]int{
1717
NEWUTS: unix.CLONE_NEWUTS,
1818
NEWPID: unix.CLONE_NEWPID,
1919
NEWCGROUP: unix.CLONE_NEWCGROUP,
20+
NEWTIME: unix.CLONE_NEWTIME,
2021
}
2122

2223
// CloneFlags parses the container's Namespaces options to set the correct

libcontainer/configs/validate/validator.go

+6
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ func namespaces(config *configs.Config) error {
116116
}
117117
}
118118

119+
if config.Namespaces.Contains(configs.NEWTIME) {
120+
if _, err := os.Stat("/proc/self/timens_offsets"); os.IsNotExist(err) {
121+
return errors.New("time namespaces aren't enabled in the kernel")
122+
}
123+
}
124+
119125
return nil
120126
}
121127

libcontainer/container_linux.go

+12
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,18 @@ func (c *Container) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Namespa
11911191
})
11921192
}
11931193

1194+
// write boottime and monotonic time ns offsets.
1195+
if c.config.Namespaces.Contains(configs.NEWTIME) && c.config.TimeOffsets != nil {
1196+
var offsetSpec bytes.Buffer
1197+
for clock, offset := range c.config.TimeOffsets {
1198+
fmt.Fprintf(&offsetSpec, "%s %d %d\n", clock, offset.Secs, offset.Nanosecs)
1199+
}
1200+
r.AddData(&Bytemsg{
1201+
Type: TimeOffsetsAttr,
1202+
Value: offsetSpec.Bytes(),
1203+
})
1204+
}
1205+
11941206
return bytes.NewReader(r.Serialize()), nil
11951207
}
11961208

libcontainer/message_linux.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
GidmapPathAttr uint16 = 27289
2424
MountSourcesAttr uint16 = 27290
2525
IdmapSourcesAttr uint16 = 27291
26+
TimeOffsetsAttr uint16 = 27292
2627
)
2728

2829
type Int32msg struct {

libcontainer/nsenter/namespace.h

+3
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@
2828
#ifndef CLONE_NEWNET
2929
# define CLONE_NEWNET 0x40000000 /* New network namespace */
3030
#endif
31+
#ifndef CLONE_NEWTIME
32+
# define CLONE_NEWTIME 0x00000080 /* New time namespace */
33+
#endif
3134

3235
#endif /* NSENTER_NAMESPACE_H */

libcontainer/nsenter/nsexec.c

+27
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ struct nlconfig_t {
104104
/* Idmap sources opened outside the container userns which will be id mapped. */
105105
char *idmapsources;
106106
size_t idmapsources_len;
107+
108+
/* Time NS offsets. */
109+
char *timensoffset;
110+
size_t timensoffset_len;
107111
};
108112

109113
/*
@@ -122,6 +126,7 @@ struct nlconfig_t {
122126
#define GIDMAPPATH_ATTR 27289
123127
#define MOUNT_SOURCES_ATTR 27290
124128
#define IDMAP_SOURCES_ATTR 27291
129+
#define TIMENSOFFSET_ATTR 27292
125130

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

355362
/* If we don't recognise a name, fallback to 0. */
356363
return 0;
@@ -445,6 +452,10 @@ static void nl_parse(int fd, struct nlconfig_t *config)
445452
config->idmapsources = current;
446453
config->idmapsources_len = payload_len;
447454
break;
455+
case TIMENSOFFSET_ATTR:
456+
config->timensoffset = current;
457+
config->timensoffset_len = payload_len;
458+
break;
448459
default:
449460
bail("unknown netlink message type %d", nlattr->nla_type);
450461
}
@@ -747,6 +758,17 @@ void receive_idmapsources(int sockfd)
747758
receive_fd_sources(sockfd, "_LIBCONTAINER_IDMAP_FDS");
748759
}
749760

761+
static void update_timens(char *map, size_t map_len)
762+
{
763+
if (map == NULL || map_len == 0)
764+
return;
765+
write_log(DEBUG, "update /proc/self/timens_offsets to '%s'", map);
766+
if (write_file(map, map_len, "/proc/self/timens_offsets") < 0) {
767+
if (errno != EPERM)
768+
bail("failed to update /proc/self/timens_offsets");
769+
}
770+
}
771+
750772
void nsexec(void)
751773
{
752774
int pipenum;
@@ -1185,6 +1207,11 @@ void nsexec(void)
11851207
bail("failed to sync with parent: SYNC_MOUNT_IDMAP_ACK: got %u", s);
11861208
}
11871209

1210+
/*
1211+
* set boottime and monotonic timens offsets.
1212+
*/
1213+
update_timens(config.timensoffset, config.timensoffset_len);
1214+
11881215
/*
11891216
* TODO: What about non-namespace clone flags that we're dropping here?
11901217
*

libcontainer/specconv/spec_linux.go

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func initMaps() {
4949
specs.IPCNamespace: configs.NEWIPC,
5050
specs.UTSNamespace: configs.NEWUTS,
5151
specs.CgroupNamespace: configs.NEWCGROUP,
52+
specs.TimeNamespace: configs.NEWTIME,
5253
}
5354

5455
mountPropagationMapping = map[string]int{
@@ -435,6 +436,9 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
435436
MemBwSchema: spec.Linux.IntelRdt.MemBwSchema,
436437
}
437438
}
439+
440+
// update timens offsets
441+
config.TimeOffsets = spec.Linux.TimeOffsets
438442
}
439443

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

0 commit comments

Comments
 (0)