Hello,

Attached are two small patches to enable the third argument of adjtime() to be
NULL, see adjtime(3). Calling __host_adjust_time() with a third argument being
NULL, causes a segfault due to the *old_adjustment = OutP->old_adjustment
statement in RPC_host_adjust_time.c.

The glibc patch sysdeps_mach_hurd_adjtime.c.diff use a dummy struct timeval to
avoid calling ___host_adjust_time() in _adjtime() with a NULL third argument.
Smarter solutions can probably be found, comments are welcome.

The gnumach patch, 80_mach_clock.patch sets the old_adjustment to oadj only if
old_adjustment is non-null. This patch is probably redundant but included here
anyway.

TODO: EINVAL should also be returned if the supplied delta is too large, as
described in adjtime(3). This would be easy to fix, by a slight modification of
adjtime.c and/or mach_clock.c.

Thanks!
Index: gnumach-1.7+git20160809/kern/mach_clock.c
===================================================================
--- gnumach-1.7+git20160809.orig/kern/mach_clock.c
+++ gnumach-1.7+git20160809/kern/mach_clock.c
@@ -533,7 +533,9 @@ host_adjust_time(host, new_adjustment, o
 	thread_bind(current_thread(), PROCESSOR_NULL);
 #endif	/* NCPUS > 1 */
 
-	*old_adjustment = oadj;
+	/* Allow *old_adjustment to be NULL: see man adjtime(3)  */
+	if (old_adjustment)
+		*old_adjustment = oadj;
 
 	return (KERN_SUCCESS);
 }
Index: glibc-2.23/sysdeps/mach/hurd/adjtime.c
===================================================================
--- glibc-2.23.orig/sysdeps/mach/hurd/adjtime.c
+++ glibc-2.23/sysdeps/mach/hurd/adjtime.c
@@ -28,16 +28,25 @@ __adjtime (const struct timeval *delta,
 {
   error_t err;
   mach_port_t hostpriv;
+  struct timeval dummy = {0, 0};
 
   err = __get_privileged_ports (&hostpriv, NULL);
   if (err)
     return __hurd_fail (EPERM);
 
-  err = __host_adjust_time (hostpriv,
-			    /* `time_value_t' and `struct timeval' are in
-                               fact identical with the names changed.  */
-			    *(time_value_t *) delta,
-			    (time_value_t *) olddelta);
+    if (olddelta)
+      err = __host_adjust_time (hostpriv,
+				/* `time_value_t' and `struct timeval' are in
+				   fact identical with the names changed.  */
+				*(time_value_t *) delta,
+				(time_value_t *) olddelta);
+    else
+      /* Handle the case when olddelta is NULL, see man adjtime(3) */
+      err = __host_adjust_time (hostpriv,
+				/* `time_value_t' and `struct timeval' are in
+				   fact identical with the names changed.  */
+				*(time_value_t *) delta,
+				(time_value_t *) &dummy);
   __mach_port_deallocate (__mach_task_self (), hostpriv);
 
   if (err)

Reply via email to