summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2011-03-28 05:35:30 -0400
committerEric S. Raymond <esr@thyrsus.com>2011-03-28 05:35:30 -0400
commit3e7fb419ed47a875888461776c3f4b6c54a16660 (patch)
treee24e3aecb2bc62e648cd70c452e946698effe24c
parenta46c1a3e1b4ce370ecb68b5b3afb7f76297a4fd4 (diff)
downloadgpsd-3e7fb419ed47a875888461776c3f4b6c54a16660.tar.gz
Double-buffer to prevent a corrupted shm read from clobbbering the user copy.
-rw-r--r--libgps_shm.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/libgps_shm.c b/libgps_shm.c
index e4f861ba..7cb63c96 100644
--- a/libgps_shm.c
+++ b/libgps_shm.c
@@ -56,6 +56,7 @@ int gps_shm_read(struct gps_data_t *gpsdata)
{
int before, after;
struct shmexport_t *shared = (struct shmexport_t *)gpsdata->privdata;
+ struct gps_data_t noclobber;
/*
* Following block of instructions must not be reordered, otherwise
@@ -70,14 +71,21 @@ int gps_shm_read(struct gps_data_t *gpsdata)
*/
before = shared->bookend1;
barrier();
- (void)memcpy((void *)gpsdata,
+ (void)memcpy((void *)&noclobber,
(void *)&shared->gpsdata,
sizeof(struct gps_data_t));
barrier();
after = shared->bookend2;
- /*@i1@*/gpsdata->privdata = shared;
- return (before == after) ? (int)sizeof(struct gps_data_t) : 0;
+ if (before != after)
+ return 0;
+ else {
+ (void)memcpy((void *)gpsdata,
+ (void *)&noclobber,
+ sizeof(struct gps_data_t));
+ /*@i1@*/gpsdata->privdata = shared;
+ return (int)sizeof(struct gps_data_t);
+ }
}
}