[Patch]: Create Global Privilege

Pierre A. Humblet pierre@phumblet.no-ip.org
Fri Dec 5 03:17:00 GMT 2003


At 10:26 AM 12/2/2003 +0100, Corinna Vinschen wrote:
>On Mon, Dec 01, 2003 at 10:55:46PM -0500, Pierre A. Humblet wrote:
>> Also, the utmp/wtmp functions use mutexes to insure safe access.
>> That creates two problems, particularly on servers:
>> - When users have private copies of Cygwin with different mounts,
>>   there can be several utmp/wtmp files. Having a global mutex isn't
>>   helpful.
>> - If the utmp/wtmp files are unique, a user may not be have the
>>   privilege to create a global mutex, so that no mutual protection
>>   is achieved.
>> Both problems could be solved very simply by using file locking.
>> Should I do that some day?
>
>Sure, go ahead.

Here it is.

In the case of wtmp, records are always appended.
A new function, "locked_append", avoids collisions.

In the case of utmp, if an entry for a tty already
exists, it is modified by the login/logout processes.
There is only one such process per tty, thus no
locking is required. If there is no entry for the tty,
a new one is safely created with the same 
"locked_append" function.

Because the lock is mandatory, reads of locked regions
will fail. The current code already handles that.

Pierre

2003-12-05  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	5 Dec 2003 03:10:55 -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_SETLK, &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++ < 4
+	 && (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