about summary refs log tree commit diff
path: root/sunrpc/svc_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'sunrpc/svc_unix.c')
-rw-r--r--sunrpc/svc_unix.c80
1 files changed, 53 insertions, 27 deletions
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
index 0ff26aaaba..a34e54dd71 100644
--- a/sunrpc/svc_unix.c
+++ b/sunrpc/svc_unix.c
@@ -284,6 +284,8 @@ svcunix_destroy (SVCXPRT *xprt)
 struct cmessage {
   struct cmsghdr cmsg;
   struct ucred cmcred;
+  /* hack to make sure we have enough memory */
+  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
 };
 
 /* XXX This is not thread safe, but since the main functions in svc.c
@@ -293,15 +295,16 @@ static struct cmessage cm;
 #endif
 
 static int
-__msgread (int sock, void *buf, size_t cnt)
+__msgread (int sock, void *data, size_t cnt)
 {
-  struct iovec iov[1];
+  struct iovec iov;
   struct msghdr msg;
+  int len;
 
-  iov[0].iov_base = buf;
-  iov[0].iov_len = cnt;
+  iov.iov_base = data;
+  iov.iov_len = cnt;
 
-  msg.msg_iov = iov;
+  msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
   msg.msg_name = NULL;
   msg.msg_namelen = 0;
@@ -319,42 +322,65 @@ __msgread (int sock, void *buf, size_t cnt)
   }
 #endif
 
-  return recvmsg (sock, &msg, 0);
+ restart:
+  len = recvmsg (sock, &msg, 0);
+  if (len >= 0)
+    {
+      if (msg.msg_flags & MSG_CTRUNC || len == 0)
+        return 0;
+      else
+        return len;
+    }
+  if (errno == EINTR)
+    goto restart;
+  return -1;
 }
 
 static int
-__msgwrite (int sock, void *buf, size_t cnt)
+__msgwrite (int sock, void *data, size_t cnt)
 {
 #ifndef SCM_CREDENTIALS
   /* We cannot implement this reliably.  */
   __set_errno (ENOSYS);
   return -1;
 #else
-  struct iovec iov[1];
+  struct iovec iov;
   struct msghdr msg;
-
-  iov[0].iov_base = buf;
-  iov[0].iov_len = cnt;
-
-  cm.cmsg.cmsg_type = SCM_CREDENTIALS;
-  cm.cmsg.cmsg_level = SOL_SOCKET;
-  cm.cmsg.cmsg_len = sizeof (struct cmessage);
-  /* XXX I'm not sure, if we really should use gete?id(), or get?id().
-     It would be much better, if the kernel could pass both to the
-     client. */
-  cm.cmcred.pid = __getpid ();
-  cm.cmcred.uid = __geteuid ();
-  cm.cmcred.gid = __getegid ();
-
-  msg.msg_iov = iov;
+  struct cmsghdr *cmsg = &cm.cmsg;
+  struct ucred cred;
+  int len;
+
+  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
+     get?id(). But since keyserv needs geteuid(), we have no other chance.
+     It would be much better, if the kernel could pass both to the server. */
+  cred.pid = __getpid ();
+  cred.uid = __geteuid ();
+  cred.gid = __getegid ();
+
+  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
+  cmsg->cmsg_level = SOL_SOCKET;
+  cmsg->cmsg_type = SCM_CREDENTIALS;
+  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
+
+  iov.iov_base = data;
+  iov.iov_len = cnt;
+
+  msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
   msg.msg_name = NULL;
   msg.msg_namelen = 0;
-  msg.msg_control = (caddr_t) &cm;
-  msg.msg_controllen = sizeof (struct cmessage);
+  msg.msg_control = cmsg;
+  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
   msg.msg_flags = 0;
 
-  return sendmsg (sock, &msg, 0);
+ restart:
+  len = sendmsg (sock, &msg, 0);
+  if (len >= 0)
+    return len;
+  if (errno == EINTR)
+    goto restart;
+  return -1;
+
 #endif
 }
 
@@ -446,8 +472,8 @@ svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
     {
       cd->x_id = msg->rm_xid;
       /* set up verifiers */
-      msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
 #ifdef SCM_CREDENTIALS
+      msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
       msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
       msg->rm_call.cb_verf.oa_length = sizeof (cm);
 #endif