at master 6.9 kB view raw
1Eliminate use of state/node files in temp directory, which are a security concern due to insecure writing of State/Node files in a temporary directory, with predictable filenames, with a possible symlink attack. 2 3Fixes CVE-2013-4184 4 5https://github.com/bleargh45/Data-UUID/pull/40 by Graham TerMarsch @bleargh45 6 7 8diff --git a/Makefile.PL b/Makefile.PL 9index 4ca26af..fb1a0f0 100644 10--- a/Makefile.PL 11+++ b/Makefile.PL 12@@ -89,30 +89,14 @@ WriteMakefile( 13 14 CONFIGURE => sub { 15 my %opt; 16- GetOptions(\%opt, 's|state-storage-directory:s', 'd|default-umask:s', 17- 'help|?', 'man') or pod2usage(2); 18+ GetOptions(\%opt, 'help|?', 'man') or pod2usage(2); 19 pod2usage(1) if $opt{help}; 20 pod2usage(-verbose => 2) if $opt{man}; 21 22 print "Configured options (run perl Makefile.PL --help for how to change this):\n"; 23 24- my $d = File::Spec->tmpdir; 25- $d = $opt{s} || $d; 26- print "\tUUID state storage: $d\n"; 27- $d =~ s/\\/\\\\/g if $^O eq 'MSWin32'; 28- 29- my $m = '0007'; 30- unless ($^O eq 'MSWin32') { 31- $m = $opt{d} || $m; 32- print "\tdefault umask: $m\n"; 33- } 34- 35- chmod(0666, sprintf("%s/%s", $d, ".UUID_NODEID")); 36- chmod(0666, sprintf("%s/%s", $d, ".UUID_STATE")); 37 return { 38- DEFINE => '-D_STDIR=' . shell_quote(c_quote($d)) 39- . ' -D' . shell_quote("__$Config{osname}__") 40- . ' -D_DEFAULT_UMASK=' . shell_quote($m) 41+ DEFINE => ' -D' . shell_quote("__$Config{osname}__") 42 }; 43 } 44 ); 45@@ -127,11 +111,9 @@ Makefile.PL - configure Makefile for Data::UUID 46 47 perl Makefile.PL [options] [EU::MM options] 48 49-perl Makefile.PL -s=/var/local/lib/data-uuid -d=0007 50+perl Makefile.PL 51 52 Options: 53- --state-storage-directory directory for storing library state information 54- --default-umask umask for files in the state storage directory 55 --help brief help message 56 --man full documentation 57 58@@ -141,18 +123,6 @@ Options can be abbreviated, see L<Getopt::Long/"Case and abbreviations">. 59 60 =over 61 62-=item --state-storage-directory 63- 64-Optional. Takes a string that is interpreted as directory for storing library 65-state information. Default is c:/tmp/ on Windows if it already exists, or the 66-operating system's temporary directory (see tmpdir in L<File::Spec/"METHODS">), 67-or /var/tmp as fallback. 68- 69-=item --default-umask 70- 71-Optional. Takes a string that is interpreted as umask for the files in the state 72-storage directory. Default is 0007. This is ignored on Windows. 73- 74 =item --help 75 76 Print a brief help message and exits. 77@@ -165,10 +135,7 @@ Prints the manual page and exits. 78 79 =head1 DESCRIPTION 80 81-B<Makefile.PL> writes the Makefile for the Data::UUID library. It is configured 82-with the options L</"--state-storage-directory"> and L</"--default-umask">. 83-Unless given, default values are used. In any case the values are printed for 84-confirmation. 85+B<Makefile.PL> writes the Makefile for the Data::UUID library. 86 87 Additionally, the usual EU::MM options are processed, see 88 L<ExtUtils::MakeMaker/"Using Attributes and Parameters">. 89diff --git a/README b/README 90index 8aaa1c2..34d53a5 100644 91--- a/README 92+++ b/README 93@@ -23,15 +23,6 @@ To install this module type the following: 94 make test 95 make install 96 97-NOTE: This module is designed to save its state information in a permanent 98-storage location. The installation script (i.e. Makefile.PL) prompts for 99-a directory name to use as a storage location for state file and defaults 100-this directory to "/var/tmp" if no directory name is provided. 101-The installation script will not accept names of directories that do not 102-exist, however, it will take the locations, which the installing user 103-has no write permissions to. In this case, the state information will not be 104-saved, which will maximize the chances of generating duplicate UUIDs. 105- 106 COPYRIGHT AND LICENCE 107 108 Copyright (C) 2001, Alexander Golomshtok 109diff --git a/UUID.h b/UUID.h 110index dc5ea28..11d6e13 100644 111--- a/UUID.h 112+++ b/UUID.h 113@@ -44,23 +44,6 @@ 114 #include <process.h> 115 #endif 116 117-#if !defined _STDIR 118-# define _STDIR "/var/tmp" 119-#endif 120-#if !defined _DEFAULT_UMASK 121-# define _DEFAULT_UMASK 0007 122-#endif 123- 124-#define UUID_STATE ".UUID_STATE" 125-#define UUID_NODEID ".UUID_NODEID" 126-#if defined __mingw32__ || (defined _WIN32 && !defined(__cygwin__)) || defined _MSC_VER 127-#define UUID_STATE_NV_STORE _STDIR"\\"UUID_STATE 128-#define UUID_NODEID_NV_STORE _STDIR"\\"UUID_NODEID 129-#else 130-#define UUID_STATE_NV_STORE _STDIR"/"UUID_STATE 131-#define UUID_NODEID_NV_STORE _STDIR"/"UUID_NODEID 132-#endif 133- 134 #define UUIDS_PER_TICK 1024 135 #ifdef _MSC_VER 136 #define I64(C) C##i64 137@@ -134,7 +117,6 @@ typedef struct _uuid_state_t { 138 typedef struct _uuid_context_t { 139 uuid_state_t state; 140 uuid_node_t nodeid; 141- perl_uuid_time_t next_save; 142 } uuid_context_t; 143 144 static void format_uuid_v1( 145diff --git a/UUID.xs b/UUID.xs 146index c3496a8..8191727 100644 147--- a/UUID.xs 148+++ b/UUID.xs 149@@ -356,29 +356,11 @@ PREINIT: 150 UV one = 1; 151 CODE: 152 RETVAL = (uuid_context_t *)PerlMemShared_malloc(sizeof(uuid_context_t)); 153- if ((fd = fopen(UUID_STATE_NV_STORE, "rb"))) { 154- fread(&(RETVAL->state), sizeof(uuid_state_t), 1, fd); 155- fclose(fd); 156- get_current_time(&timestamp); 157- RETVAL->next_save = timestamp; 158- } 159- if ((fd = fopen(UUID_NODEID_NV_STORE, "rb"))) { 160- pid_t *hate = (pid_t *) &(RETVAL->nodeid); 161- fread(&(RETVAL->nodeid), sizeof(uuid_node_t), 1, fd ); 162- fclose(fd); 163- 164- *hate += getpid(); 165- } else { 166+ 167 get_random_info(seed); 168 seed[0] |= 0x80; 169 memcpy(&(RETVAL->nodeid), seed, sizeof(uuid_node_t)); 170- mask = umask(_DEFAULT_UMASK); 171- if ((fd = fopen(UUID_NODEID_NV_STORE, "wb"))) { 172- fwrite(&(RETVAL->nodeid), sizeof(uuid_node_t), 1, fd); 173- fclose(fd); 174- }; 175- umask(mask); 176- } 177+ 178 errno = 0; 179 #if DU_THREADSAFE 180 MUTEX_LOCK(&instances_mutex); 181@@ -415,17 +397,6 @@ PPCODE: 182 self->state.node = self->nodeid; 183 self->state.ts = timestamp; 184 self->state.cs = clockseq; 185- if (timestamp > self->next_save ) { 186- mask = umask(_DEFAULT_UMASK); 187- if((fd = fopen(UUID_STATE_NV_STORE, "wb"))) { 188- LOCK(fd); 189- fwrite(&(self->state), sizeof(uuid_state_t), 1, fd); 190- UNLOCK(fd); 191- fclose(fd); 192- } 193- umask(mask); 194- self->next_save = timestamp + (10 * 10 * 1000 * 1000); 195- } 196 ST(0) = make_ret(uuid, ix); 197 XSRETURN(1); 198 199@@ -585,14 +556,6 @@ CODE: 200 MUTEX_UNLOCK(&instances_mutex); 201 if (count == 0) { 202 #endif 203- mask = umask(_DEFAULT_UMASK); 204- if ((fd = fopen(UUID_STATE_NV_STORE, "wb"))) { 205- LOCK(fd); 206- fwrite(&(self->state), sizeof(uuid_state_t), 1, fd); 207- UNLOCK(fd); 208- fclose(fd); 209- }; 210- umask(mask); 211 PerlMemShared_free(self); 212 #if DU_THREADSAFE 213 } 214