Discussion:
[chrony-users] [PATCH] main: imply -x if time can't be set
Christian Ehrhardt
2018-03-07 11:34:17 UTC
Permalink
In unprivileged containers even after e8096330 "sys_linux: don't keep
CAP_SYS_TIME with -x option" default installations
will still run without an explicit -x being set and therefore fail by
missing CAP_SYS_TIME.

Usually users want services to "just work" which in a non-CAP_SYS_TIME
environment means that chrony will fulfil just the NTP serving task but
not the local time control.

Therefore imply -x in those environments.

Signed-off-by: Christian Ehrhardt <***@canonical.com>
---
main.c | 5 +++++
sys.c | 11 +++++++++++
sys.h | 3 +++
sys_linux.c | 10 ++++++++++
sys_linux.h | 2 ++
5 files changed, 31 insertions(+)

diff --git a/main.c b/main.c
index a2202e9..7a6f61c 100644
--- a/main.c
+++ b/main.c
@@ -499,6 +499,11 @@ int main
if (getuid() && !client_only)
LOG_FATAL("Not superuser");

+ if (clock_control && !SYS_IsTimeAdjustable()) {
+ LOG(LOGS_WARN, "Time not adjustable, implying -x (do not set system clock)");
+ clock_control = 0;
+ }
+
/* Turn into a daemon */
if (!nofork) {
go_daemon();
diff --git a/sys.c b/sys.c
index 4d68b37..4581a66 100644
--- a/sys.c
+++ b/sys.c
@@ -94,6 +94,17 @@ SYS_Finalise(void)

/* ================================================== */

+int SYS_IsTimeAdjustable()
+{
+#if defined(LINUX) && defined (FEAT_PRIVDROP)
+ return SYS_Linux_IsTimeAdjustable();
+#elif
+ return true;
+#endif
+}
+
+/* ================================================== */
+
void SYS_DropRoot(uid_t uid, gid_t gid)
{
#if defined(LINUX) && defined (FEAT_PRIVDROP)
diff --git a/sys.h b/sys.h
index cb726f2..a40ea96 100644
--- a/sys.h
+++ b/sys.h
@@ -38,6 +38,9 @@ extern void SYS_Finalise(void);
/* Drop root privileges to the specified user and group */
extern void SYS_DropRoot(uid_t uid, gid_t gid);

+/* Check if time is adjustable, e.g. lack of CAP_SYS_TIME on linux containers */
+extern int SYS_IsTimeAdjustable(void);
+
/* Enable a system call filter to allow only system calls
which chronyd normally needs after initialization */
extern void SYS_EnableSystemCallFilter(int level);
diff --git a/sys_linux.c b/sys_linux.c
index f445727..695d3d4 100644
--- a/sys_linux.c
+++ b/sys_linux.c
@@ -413,6 +413,16 @@ SYS_Linux_Finalise(void)

/* ================================================== */

+int SYS_Linux_IsTimeAdjustable(void)
+{
+ if (CAP_IS_SUPPORTED(CAP_SYS_TIME) && cap_get_bound(CAP_SYS_TIME))
+ return 1;
+ else
+ return 0;
+}
+
+/* ================================================== */
+
#ifdef FEAT_PRIVDROP
void
SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
diff --git a/sys_linux.h b/sys_linux.h
index 799ae9a..301d025 100644
--- a/sys_linux.h
+++ b/sys_linux.h
@@ -31,6 +31,8 @@ extern void SYS_Linux_Initialise(void);

extern void SYS_Linux_Finalise(void);

+extern int SYS_Linux_IsTimeAdjustable(void);
+
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);

extern void SYS_Linux_EnableSystemCallFilter(int level);
--
2.7.4
--
To unsubscribe email chrony-users-***@chrony.tuxfamily.org
with "unsubscribe" in the subject.
For help email chrony-users-***@chrony.tuxfamily.org
with "help" in the subject.
Trouble? Email ***@chrony.tuxfamily.org.
Christian Ehrhardt
2018-03-07 12:57:52 UTC
Permalink
I beg your pardon, I initially intended to file a bug (this list) but
eventually wrote a patch.
I just submitted to -dev where a patch is more correct, so ignore this mail
over here in favor of the one on the -dev list.

On Wed, Mar 7, 2018 at 12:34 PM, Christian Ehrhardt <
Post by Christian Ehrhardt
In unprivileged containers even after e8096330 "sys_linux: don't keep
CAP_SYS_TIME with -x option" default installations
will still run without an explicit -x being set and therefore fail by
missing CAP_SYS_TIME.
Usually users want services to "just work" which in a non-CAP_SYS_TIME
environment means that chrony will fulfil just the NTP serving task but
not the local time control.
Therefore imply -x in those environments.
---
main.c | 5 +++++
sys.c | 11 +++++++++++
sys.h | 3 +++
sys_linux.c | 10 ++++++++++
sys_linux.h | 2 ++
5 files changed, 31 insertions(+)
diff --git a/main.c b/main.c
index a2202e9..7a6f61c 100644
--- a/main.c
+++ b/main.c
@@ -499,6 +499,11 @@ int main
if (getuid() && !client_only)
LOG_FATAL("Not superuser");
+ if (clock_control && !SYS_IsTimeAdjustable()) {
+ LOG(LOGS_WARN, "Time not adjustable, implying -x (do not set system clock)");
+ clock_control = 0;
+ }
+
/* Turn into a daemon */
if (!nofork) {
go_daemon();
diff --git a/sys.c b/sys.c
index 4d68b37..4581a66 100644
--- a/sys.c
+++ b/sys.c
@@ -94,6 +94,17 @@ SYS_Finalise(void)
/* ================================================== */
+int SYS_IsTimeAdjustable()
+{
+#if defined(LINUX) && defined (FEAT_PRIVDROP)
+ return SYS_Linux_IsTimeAdjustable();
+#elif
+ return true;
+#endif
+}
+
+/* ================================================== */
+
void SYS_DropRoot(uid_t uid, gid_t gid)
{
#if defined(LINUX) && defined (FEAT_PRIVDROP)
diff --git a/sys.h b/sys.h
index cb726f2..a40ea96 100644
--- a/sys.h
+++ b/sys.h
@@ -38,6 +38,9 @@ extern void SYS_Finalise(void);
/* Drop root privileges to the specified user and group */
extern void SYS_DropRoot(uid_t uid, gid_t gid);
+/* Check if time is adjustable, e.g. lack of CAP_SYS_TIME on linux containers */
+extern int SYS_IsTimeAdjustable(void);
+
/* Enable a system call filter to allow only system calls
which chronyd normally needs after initialization */
extern void SYS_EnableSystemCallFilter(int level);
diff --git a/sys_linux.c b/sys_linux.c
index f445727..695d3d4 100644
--- a/sys_linux.c
+++ b/sys_linux.c
@@ -413,6 +413,16 @@ SYS_Linux_Finalise(void)
/* ================================================== */
+int SYS_Linux_IsTimeAdjustable(void)
+{
+ if (CAP_IS_SUPPORTED(CAP_SYS_TIME) && cap_get_bound(CAP_SYS_TIME))
+ return 1;
+ else
+ return 0;
+}
+
+/* ================================================== */
+
#ifdef FEAT_PRIVDROP
void
SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
diff --git a/sys_linux.h b/sys_linux.h
index 799ae9a..301d025 100644
--- a/sys_linux.h
+++ b/sys_linux.h
@@ -31,6 +31,8 @@ extern void SYS_Linux_Initialise(void);
extern void SYS_Linux_Finalise(void);
+extern int SYS_Linux_IsTimeAdjustable(void);
+
extern void SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control);
extern void SYS_Linux_EnableSystemCallFilter(int level);
--
2.7.4
--
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
Loading...