diff mbox

[Hurd] bind() fails when umask is 0000

Message ID 20140825122157.GC3213@type.bordeaux.inria.fr
State Superseded
Headers show

Commit Message

Samuel Thibault Aug. 25, 2014, 12:21 p.m. UTC
Hello,

When umask is 0000, bind()'s call to __ifsock_getsockaddr() fails with
EPERM since the node was created as 0000. The following basically does
the following, which looks up the translator and gets the address before
fixing permissions and showing the file:

bind() {
...
	dir_mkfile(dir, O_CREAT, 0666, &node);
	file_set_translator(node, ...)
	dir_lookup(node, "", 0, 0, ..., &ifsock);
	ifsock_getsockaddr(ifsock, &aport);
	file_chmod(node, 0666 & ~_hurd_umask);
	dir_link(dir, node, name, 1);
...
}

Samuel

2014-08-25  Samuel Thibault  <samuel.thibault@ens-lyon.org>

	Fix bind when umask is e.g. 0000.

        * sysdeps/mach/hurd/bind.c (__bind): Pass mode 0666 to __dir_mkfile
        instead of final mode, so that call __ifsock_getsockaddr can always
        succeed, before calling __file_chmod to fix the mode according to umask,
        before calling __dir_link to show the file.
diff mbox

Patch

--- sysdeps/mach/hurd/bind.c.orig	2014-08-25 14:11:11.245229537 +0200
+++ sysdeps/mach/hurd/bind.c	2014-08-25 14:11:35.892517639 +0200
@@ -40,7 +40,7 @@ 
       char *name = _hurd_sun_path_dupa (addr, len);
       /* For the local domain, we must create a node in the filesystem
 	 using the ifsock translator and then fetch the address from it.  */
-      file_t dir, node;
+      file_t dir, node, ifsock;
       char *n;
 
       dir = __file_name_split (name, &n);
@@ -48,7 +48,7 @@ 
 	return -1;
 
       /* Create a new, unlinked node in the target directory.  */
-      err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node);
+      err = __dir_mkfile (dir, O_CREAT, 0666, &node);
 
       if (! err)
 	{
@@ -61,36 +61,43 @@ 
 				       MACH_MSG_TYPE_COPY_SEND);
 	  if (! err)
 	    {
-	      /* Link the node, now a socket, into the target directory.  */
-	      err = __dir_link (dir, node, n, 1);
-	      if (err == EEXIST)
-		err = EADDRINUSE;
+	      enum retry_type doretry;
+	      char retryname[1024];
+	      /* Get a port to the ifsock translator.  */
+	      err = __dir_lookup(node, "", 0, 0, &doretry, retryname, &ifsock);
+	      if (! err)
+		if (doretry != FS_RETRY_NORMAL || retryname[0] != '\0')
+		  err = EADDRINUSE;
 	    }
-	  __mach_port_deallocate (__mach_task_self (), node);
 	  if (! err)
 	    {
-	      /* Get a port to the ifsock translator.  */
-	      file_t ifsock = __file_name_lookup_under (dir, n, 0, 0);
-	      if (ifsock == MACH_PORT_NULL)
-		{
-		  err = errno;
-		  /* If we failed, get rid of the node we created.  */
-		  __dir_unlink (dir, n);
-		}
-	      else
+	      /* Get the address port.  */
+	      err = __ifsock_getsockaddr (ifsock, &aport);
+	      if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+		/* We are not talking to /hurd/ifsock.  Probably
+		   someone came in after we linked our node, unlinked
+		   it, and replaced it with a different node, before we
+		   did our lookup.  Treat it as if our link had failed
+		   with EEXIST.  */
+		err = EADDRINUSE;
+	      if (! err)
 		{
-		  /* Get the address port.  */
-		  err = __ifsock_getsockaddr (ifsock, &aport);
-		  if (err == MIG_BAD_ID || err == EOPNOTSUPP)
-		    /* We are not talking to /hurd/ifsock.  Probably
-		       someone came in after we linked our node, unlinked
-		       it, and replaced it with a different node, before we
-		       did our lookup.  Treat it as if our link had failed
-		       with EEXIST.  */
-		    err = EADDRINUSE;
+		  /* Fix the access mode before showing the file.  */
+		  err = __file_chmod (node, 0666 & ~_hurd_umask);
+		  if (! err)
+		    {
+		      /* Link the node, now a socket with proper mode, into the
+		       * target directory.  */
+		      err = __dir_link (dir, node, n, 1);
+		      if (err == EEXIST)
+			err = EADDRINUSE;
+		    }
+		  if (err)
+		    __mach_port_deallocate (__mach_task_self (), aport);
 		}
 	      __mach_port_deallocate (__mach_task_self (), ifsock);
 	    }
+	  __mach_port_deallocate (__mach_task_self (), node);
 	}
       __mach_port_deallocate (__mach_task_self (), dir);