From 3b8ff12d03f5ebe0fdcf4665a1345e5fe4a26bd4 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 22 Aug 2011 17:15:15 +0200 Subject: [PATCH] fix PPS without -N --- gpsd-priv.patch | 193 ++++++++++++++++++++++++++++++++++++++++++++++++ gpsd.spec | 2 + 2 files changed, 195 insertions(+) create mode 100644 gpsd-priv.patch diff --git a/gpsd-priv.patch b/gpsd-priv.patch new file mode 100644 index 0000000..8d3afe7 --- /dev/null +++ b/gpsd-priv.patch @@ -0,0 +1,193 @@ +commit 76fbaa2fd53baf74cccc1fb03c68f731672bc921 +Author: Eric S. Raymond +Date: Fri Aug 19 04:04:42 2011 -0400 + + The -N option no longer drops privileges. + + The price is that only devices specified on the gpsd commmand line will + do PPS, because the calls to set line discipline stop being available + after we drop privileges. In practice, this shouldn't be a problem, + as PPS devices ar RS232 ports that can't be hotplugged and thus *must* + be specified on the command line. + + All regression tests pass. + +diff --git a/NEWS b/NEWS +index 6090e43..473c68b 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,3 +1,7 @@ ++* Fri Aug 19 2011 Eric S. Raymond - 3.1~dev ++ Change -N semantics so it only suppresses backgrounding; privileges ++ are now dropped as in normal background operation. ++ + * Fri Aug 19 2011 Eric S. Raymond - 3.0 + POLL subobject name changes: fixes -> tpv, skyview -> sky. + Fix a timestamp-clobbering bug in the C library revealed by an +diff --git a/gpsd.c b/gpsd.c +index d854567..177033c 100644 +--- a/gpsd.c ++++ b/gpsd.c +@@ -1780,6 +1780,7 @@ int main(int argc, char *argv[]) + bool go_background = true; + struct timeval tv; + const struct gps_type_t **dp; ++ bool in_restart; + + #ifdef PPS_ENABLE + /*@-nullpass@*/ +@@ -1989,16 +1990,22 @@ int main(int argc, char *argv[]) + gpsd_report(LOG_PROG, "shared-segment creation succeeded,\n"); + #endif /* SHM_EXPORT_ENABLE */ + +- /* +- * Drop privileges. +- * +- * Yes, the test for this is non-orthogonal and ugly. The problem +- * is that there is a line-discipline setup call in the PPS +- * support, way later on, that require root (see ntpshm.c and +- * look for "requires root"). We've overloaded -N with the meaning +- * "don't drop privileges" pending a better solution. ++ /* ++ * We open devices specified on the command line *before* dropping ++ * privileges in case one of them is a serial device with PPS support ++ * and we need to set the line discipline, which requires root. + */ +- if (getuid() == 0 && go_background) { ++ in_restart = false; ++ for (i = optind; i < argc; i++) { ++ if (!add_device(argv[i])) { ++ gpsd_report(LOG_ERROR, ++ "initial GPS device %s open failed\n", ++ argv[i]); ++ } ++ } ++ ++ /* drop privileges */ ++ if (getuid() == 0) { + struct passwd *pw; + struct stat stb; + +@@ -2049,6 +2056,7 @@ int main(int argc, char *argv[]) + if (allocated_device(&devices[dfd])) + (void)gpsd_wrap(&devices[dfd]); + } ++ in_restart = true; + gpsd_report(LOG_WARN, "gpsd restarted by SIGHUP\n"); + } + +@@ -2072,13 +2080,19 @@ int main(int argc, char *argv[]) + /* initialize the GPS context's time fields */ + gpsd_time_init(&context, time(NULL)); + +- for (i = optind; i < argc; i++) { +- if (!add_device(argv[i])) { +- gpsd_report(LOG_ERROR, +- "GPS device %s open failed\n", +- argv[i]); ++ /* ++ * If we got here via SIGINT, reopen any command-line devices. PPS ++ * through these won't work, as we've dropped privileges and can ++ * no longer change line disciplines. ++ */ ++ if (in_restart) ++ for (i = optind; i < argc; i++) { ++ if (!add_device(argv[i])) { ++ gpsd_report(LOG_ERROR, ++ "GPS device %s open failed\n", ++ argv[i]); ++ } + } +- } + + while (0 == signalled) { + (void)memcpy((char *)&rfds, (char *)&all_fds, sizeof(rfds)); +diff --git a/gpsd.xml b/gpsd.xml +index d548372..1ecbfee 100644 +--- a/gpsd.xml ++++ b/gpsd.xml +@@ -193,8 +193,8 @@ nonexistent in USB GPSes which lack a DTR line.) + + + -N +-Don't daemonize; run in foreground. Also suppresses +-privilege-dropping. This switch is mainly useful for debugging. ++Don't daemonize; run in foreground. ++This switch is mainly useful for debugging. + + + +@@ -795,6 +795,12 @@ supported. + The ISGPS used for RTCM2 and subframes decoder logic is + sufficiently convoluted to confuse some compiler optimizers, notably + in GCC 3.x at -O2, into generating bad code. ++ ++Devices meant to to use PPS for high-precision timekeeping may ++fail if they are specifed after startup by a control-socket command, ++as opposed to on the daemon's original command line. (Root privileges ++are dropped early, and some Unix varients require them in order to set ++the PPS line discipline.) + + FILES + +commit a59c0026a531f338a1140c55a039792e31fd14e1 +Author: Eric S. Raymond +Date: Mon Aug 22 14:44:10 2011 -0400 + + Try to open the right chrony socket... + + ...now that command-line devices are opened vefore privilege-dropping. + +diff --git a/ntpshm.c b/ntpshm.c +index 0c43146..305df88 100644 +--- a/ntpshm.c ++++ b/ntpshm.c +@@ -565,21 +565,15 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) + char chrony_path[PATH_MAX]; + + gpsd_report(LOG_PROG, "PPS Create Thread gpsd_ppsmonitor\n"); +- /* TODO the socket for root would be +- * /var/run/chrony.ttyXX.sock +- * for now it is always +- * /tmp/chrony.ttyXX.sock +- */ +-#ifdef __UNUSED__ +- /* sadly root was dropped very early, until a way if found to run this +- * before dropping root it will not work. */ +- if( 0 == getuid() ) { +- /* only root can use /var/run */ ++ ++ if ( 0 == getuid() ) { ++ /* this case will fire on command-line devices; ++ * they're opened before priv-dropping. Matters because ++ * only root can use /var/run. ++ */ + (void)snprintf(chrony_path, sizeof (chrony_path), + "/var/run/chrony.%s.sock", basename(session->gpsdata.dev.path)); +- } else +-#endif +- { ++ } else { + (void)snprintf(chrony_path, sizeof (chrony_path), + "/tmp/chrony.%s.sock", basename(session->gpsdata.dev.path)); + } + +commit 056da4ced52bc009a5f5bbfaaae475076164cc61 +Author: Gary E. Miller +Date: Mon Aug 22 15:19:25 2011 -0700 + + Fix typo in log message. + +diff --git a/ntpshm.c b/ntpshm.c +index 305df88..74af002 100644 +--- a/ntpshm.c ++++ b/ntpshm.c +@@ -579,7 +579,7 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) + } + + if (access(chrony_path, F_OK) != 0) { +- gpsd_report(LOG_PROG, "PPS chrony socket %s doesn't exist", chrony_path); ++ gpsd_report(LOG_PROG, "PPS chrony socket %s doesn't exist\n", chrony_path); + } else { + chronyfd = netlib_localsocket(chrony_path, SOCK_DGRAM); + if (chronyfd < 0) diff --git a/gpsd.spec b/gpsd.spec index 7436064..473f3c0 100644 --- a/gpsd.spec +++ b/gpsd.spec @@ -12,6 +12,7 @@ Source11: gpsd.sysconfig BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # fix RPATH, CFLAGS and revision.h Patch0: gpsd-scons.patch +Patch1: gpsd-priv.patch BuildRequires: dbus-devel dbus-glib-devel ncurses-devel xmlto python-devel BuildRequires: scons desktop-file-utils bluez-libs-devel pps-tools-devel @@ -73,6 +74,7 @@ can run on a serial terminal or terminal emulator. %prep %setup -q %patch0 -p1 -b .scons +%patch1 -p1 -b .priv echo '#define REVISION "release-%{version}-%{release}"' > revision.h