[Patch]: Create Global Privilege

Pierre A. Humblet pierre@phumblet.no-ip.org
Sat Dec 6 02:30:00 GMT 2003


At 02:54 PM 12/5/2003 +0100, Corinna Vinschen wrote:
>On Dec  5 08:02, Pierre A. Humblet wrote:
>> At 12:14 PM 12/5/2003 +0100, Corinna Vinschen wrote:
>> >Two questions:
>> >
>
>> >What is the advantage of using a finite loop with fcntl(F_SETLK) over
>> >using fcntl(F_SETLKW) just once?  This seems potentially less secure
>> >than F_SETLKW and also less secure than the former Mutex solution.
>> 
>> The only reason is that F_SETLKW doesn't work on 9X so you need
>> a loop there anyway. But thinking more about it, we should have both
>> F_SETLKW and a loop. On NT the loop will never kick in. On 9x F_SETLKW 
>> works like F_SETLK and the loop is useful. The loop could also be made
>> much longer.
>
>I agree.  Are you going to change your patch accordingly?

Sure, here it is. BTW, F_SETLKW is yucky, at least on NT4. Not only
the fcntl call isn't interruptible but the process itself can't be 
killed with kill -9 while waiting. The sig thread itself waits during
the close() call in the exit sequence.
Also a thread can deadlock by locking overlapping file segments.
This is FYI, it doesn't matter greatly here.   

Pierre

2003-12-06  Pierre Humblet <pierre.humblet@ieee.org>

	* syscalls.cc (locked_append): New.
	(updwtmp): Remove mutex code and call locked_append.
	(pututline): Ditto.
-------------- next part --------------
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.301
diff -u -p -r1.301 syscalls.cc
--- syscalls.cc	28 Nov 2003 20:55:58 -0000	1.301
+++ syscalls.cc	6 Dec 2003 01:06:35 -0000
@@ -2553,28 +2553,37 @@ ffs (int i)
   return table[x >> a] + a;
 }

+static void
+locked_append (int fd, const void * buf, size_t size)
+{
+  struct __flock64 lock_buffer = {F_WRLCK, SEEK_SET, 0, 0, 0};
+  int count = 0;
+
+  do
+    if ((lock_buffer.l_start = lseek64 (fd, 0, SEEK_END)) != (_off64_t)-1
+	&& fcntl_worker (fd, F_SETLKW, &lock_buffer) != -1)
+      {
+	if (lseek64 (fd, 0, SEEK_END) != (_off64_t)-1)
+	  write (fd, buf, size);
+	lock_buffer.l_type = F_UNLCK;
+	fcntl_worker (fd, F_SETLK, &lock_buffer);
+	break;
+      }
+  while (count++ < 1000
+	 && (errno == EACCES || errno == EAGAIN)
+	 && !usleep (1000));
+}
+
 extern "C" void
 updwtmp (const char *wtmp_file, const struct utmp *ut)
 {
-  /* Writing to wtmp must be atomic to prevent mixed up data. */
-  char mutex_name[CYG_MAX_PATH];
-  HANDLE mutex;
   int fd;

-  mutex = CreateMutex (NULL, FALSE, shared_name (mutex_name, "wtmp_mutex", 0));
-  if (mutex)
-    while (WaitForSingleObject (mutex, INFINITE) == WAIT_ABANDONED)
-      ;
-  if ((fd = open (wtmp_file, O_WRONLY | O_APPEND | O_BINARY, 0)) >= 0)
+  if ((fd = open (wtmp_file, O_WRONLY | O_BINARY, 0)) >= 0)
     {
-      write (fd, ut, sizeof *ut);
+      locked_append (fd, ut, sizeof *ut);
       close (fd);
     }
-  if (mutex)
-    {
-      ReleaseMutex (mutex);
-      CloseHandle (mutex);
-    }
 }

 extern "C" void
@@ -2783,25 +2792,15 @@ pututline (struct utmp *ut)
 		ut->ut_type, ut->ut_pid, ut->ut_line, ut->ut_id);
   debug_printf ("ut->ut_user '%s', ut->ut_host '%s'\n",
 		ut->ut_user, ut->ut_host);
-  /* Read/write to utmp must be atomic to prevent overriding data
-     by concurrent processes. */
-  char mutex_name[CYG_MAX_PATH];
-  HANDLE mutex = CreateMutex (NULL, FALSE,
-			      shared_name (mutex_name, "utmp_mutex", 0));
-  if (mutex)
-    while (WaitForSingleObject (mutex, INFINITE) == WAIT_ABANDONED)
-      ;
+
   struct utmp *u;
   if ((u = getutid (ut)))
-    lseek (utmp_fd, -sizeof *ut, SEEK_CUR);
-  else
-    lseek (utmp_fd, 0, SEEK_END);
-  write (utmp_fd, ut, sizeof *ut);
-  if (mutex)
     {
-      ReleaseMutex (mutex);
-      CloseHandle (mutex);
+      lseek (utmp_fd, -sizeof *ut, SEEK_CUR);
+      write (utmp_fd, ut, sizeof *ut);
     }
+  else
+    locked_append (utmp_fd, ut, sizeof *ut);
 }

 extern "C"


More information about the Cygwin-patches mailing list