[Wine-patches] [eter-1.0.12] fix eterbug #6900

Alexander Morozov amorozov на etersoft.ru
Пт Апр 1 21:10:18 MSD 2011


----------- следующая часть -----------
From 4502b8fe8ea9f24ddb2165704332f003a1b0295b Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard на winehq.org>
Date: Wed, 1 Jul 2009 12:11:53 +0200
Subject: [eter-1.0.12 1/4] ntdll: Avoid the close-on-exec race with recvmsg() on kernels that support this.

---
 dlls/ntdll/server.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 7651a17..a2ba2cd 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -81,6 +81,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(server);
 #define SCM_RIGHTS 1
 #endif
 
+#ifndef MSG_CMSG_CLOEXEC
+#define MSG_CMSG_CLOEXEC 0
+#endif
+
 #define SOCKETNAME "socket"        /* name of the socket file */
 #define LOCKNAME   "lock"          /* name of the lock file */
 
@@ -406,12 +410,12 @@ static int receive_fd( obj_handle_t *handle )
 
     for (;;)
     {
-        if ((ret = recvmsg( fd_socket, &msghdr, 0 )) > 0)
+        if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0)
         {
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
             fd = cmsg.fd;
 #endif
-            if (fd != -1) fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
+            if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
             return fd;
         }
         if (!ret) break;
-- 
1.7.4.2

----------- следующая часть -----------
From fc070a5cd9c56f3483bf02a9d39a0f791ffbbccf Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard на winehq.org>
Date: Thu, 30 Sep 2010 11:53:07 +0200
Subject: [eter-1.0.12 2/4] server: Make the fd passing code slightly more portable.

---
 dlls/ntdll/server.c |   76 +++++++++++++++++--------------------------
 server/request.c    |   88 ++++++++++++++++++++++++++++-----------------------
 2 files changed, 78 insertions(+), 86 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index a2ba2cd..4cbe790 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -88,20 +88,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(server);
 #define SOCKETNAME "socket"        /* name of the socket file */
 #define LOCKNAME   "lock"          /* name of the lock file */
 
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-/* data structure used to pass an fd with sendmsg/recvmsg */
-struct cmsg_fd
-{
-    struct
-    {
-        size_t len;   /* size of structure */
-        int    level; /* SOL_SOCKET */
-        int    type;  /* SCM_RIGHTS */
-    } header;
-    int fd;          /* fd to pass */
-};
-#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-
 timeout_t server_start_time = 0;  /* time of server startup */
 
 sigset_t server_block_set;  /* signals to block during server calls */
@@ -329,35 +315,36 @@ void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sig
  */
 void CDECL wine_server_send_fd( int fd )
 {
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-    struct cmsg_fd cmsg;
-#endif
     struct send_fd data;
     struct msghdr msghdr;
     struct iovec vec;
     int ret;
 
-    vec.iov_base = (void *)&data;
-    vec.iov_len  = sizeof(data);
-
-    msghdr.msg_name    = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov     = &vec;
-    msghdr.msg_iovlen  = 1;
-
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrights    = (void *)&fd;
     msghdr.msg_accrightslen = sizeof(fd);
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.header.level = SOL_SOCKET;
-    cmsg.header.type  = SCM_RIGHTS;
-    cmsg.fd           = fd;
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
+    char cmsg_buffer[256];
+    struct cmsghdr *cmsg;
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
     msghdr.msg_flags      = 0;
+    cmsg = CMSG_FIRSTHDR( &msghdr );
+    cmsg->cmsg_len   = CMSG_LEN( sizeof(fd) );
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type  = SCM_RIGHTS;
+    *(int *)CMSG_DATA(cmsg) = fd;
+    msghdr.msg_controllen = cmsg->cmsg_len;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+
+    vec.iov_base = (void *)&data;
+    vec.iov_len  = sizeof(data);
+
     data.tid = GetCurrentThreadId();
     data.fd  = fd;
 
@@ -380,24 +367,16 @@ void CDECL wine_server_send_fd( int fd )
 static int receive_fd( obj_handle_t *handle )
 {
     struct iovec vec;
-    int ret, fd;
-
-#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     struct msghdr msghdr;
+    int ret, fd = -1;
 
-    fd = -1;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrights    = (void *)&fd;
     msghdr.msg_accrightslen = sizeof(fd);
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    struct msghdr msghdr;
-    struct cmsg_fd cmsg;
-
-    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.header.level = SOL_SOCKET;
-    cmsg.header.type  = SCM_RIGHTS;
-    cmsg.fd           = -1;
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
+    char cmsg_buffer[256];
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
     msghdr.msg_flags      = 0;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
@@ -413,8 +392,13 @@ static int receive_fd( obj_handle_t *handle )
         if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0)
         {
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-            fd = cmsg.fd;
-#endif
+            struct cmsghdr *cmsg;
+            for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
+            {
+                if (cmsg->cmsg_level != SOL_SOCKET) continue;
+                if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
+            }
+#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
             if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
             return fd;
         }
diff --git a/server/request.c b/server/request.c
index 4dd6aea..7c10e6f 100644
--- a/server/request.c
+++ b/server/request.c
@@ -126,23 +126,6 @@ int config_dir_fd = -1;    /* file descriptor for the config dir */
 static struct master_socket *master_socket;  /* the master socket object */
 static struct timeout_user *master_timeout;
 
-/* socket communication static structures */
-static struct iovec myiovec;
-static struct msghdr msghdr;
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-struct cmsg_fd
-{
-    struct
-    {
-        size_t len;   /* size of structure */
-        int    level; /* SOL_SOCKET */
-        int    type;  /* SCM_RIGHTS */
-    } header;
-    int fd;           /* fd to pass */
-};
-static struct cmsg_fd cmsg = { { sizeof(cmsg.header) + sizeof(cmsg.fd), SOL_SOCKET, SCM_RIGHTS }, -1 };
-#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-
 /* complain about a protocol error and terminate the client connection */
 void fatal_protocol_error( struct thread *thread, const char *err, ... )
 {
@@ -359,25 +342,41 @@ error:
 /* receive a file descriptor on the process socket */
 int receive_fd( struct process *process )
 {
+    struct iovec vec;
     struct send_fd data;
-    int fd, ret;
+    struct msghdr msghdr;
+    int fd = -1, ret;
 
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(int);
     msghdr.msg_accrights = (void *)&fd;
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.fd = -1;
+    char cmsg_buffer[256];
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
+    msghdr.msg_flags      = 0;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
-    myiovec.iov_base = (void *)&data;
-    myiovec.iov_len  = sizeof(data);
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+    vec.iov_base = (void *)&data;
+    vec.iov_len  = sizeof(data);
 
     ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
+
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-    fd = cmsg.fd;
-#endif
+    if (ret > 0)
+    {
+        struct cmsghdr *cmsg;
+        for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
+        {
+            if (cmsg->cmsg_level != SOL_SOCKET) continue;
+            if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
+        }
+    }
+#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
     if (ret == sizeof(data))
     {
@@ -412,6 +411,7 @@ int receive_fd( struct process *process )
     {
         fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n",
                  process->id, ret );
+        if (fd != -1) close( fd );
         kill_process( process, 1 );
     }
     else
@@ -429,23 +429,37 @@ int receive_fd( struct process *process )
 /* send an fd to a client */
 int send_client_fd( struct process *process, int fd, obj_handle_t handle )
 {
+    struct iovec vec;
+    struct msghdr msghdr;
     int ret;
 
-    if (debug_level)
-        fprintf( stderr, "%04x: *fd* %04x -> %d\n",
-                 current ? current->id : process->id, handle, fd );
-
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(fd);
     msghdr.msg_accrights = (void *)&fd;
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.fd = fd;
+    char cmsg_buffer[256];
+    struct cmsghdr *cmsg;
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
+    msghdr.msg_flags      = 0;
+    cmsg = CMSG_FIRSTHDR( &msghdr );
+    cmsg->cmsg_len   = CMSG_LEN( sizeof(fd) );
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type  = SCM_RIGHTS;
+    *(int *)CMSG_DATA(cmsg) = fd;
+    msghdr.msg_controllen = cmsg->cmsg_len;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
-    myiovec.iov_base = (void *)&handle;
-    myiovec.iov_len  = sizeof(handle);
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+
+    vec.iov_base = (void *)&handle;
+    vec.iov_len  = sizeof(handle);
+
+    if (debug_level)
+        fprintf( stderr, "%04x: *fd* %04x -> %d\n", current ? current->id : process->id, handle, fd );
 
     ret = sendmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
 
@@ -797,12 +811,6 @@ void open_master_socket(void)
         acquire_lock();
     }
 
-    /* setup msghdr structure constant fields */
-    msghdr.msg_name    = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov     = &myiovec;
-    msghdr.msg_iovlen  = 1;
-
     /* init the process tracing mechanism */
     init_tracing_mechanism();
 }
-- 
1.7.4.2

----------- следующая часть -----------
From dcaf98a2ef6a88ab95e9e088b5de9bdcac3c707e Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard на winehq.org>
Date: Thu, 30 Sep 2010 17:05:13 +0200
Subject: [eter-1.0.12 3/4] ntdll: Add support for retrieving the server pid from the socket credentials.

---
 dlls/ntdll/server.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 4cbe790..23cb053 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -93,6 +93,7 @@ timeout_t server_start_time = 0;  /* time of server startup */
 sigset_t server_block_set;  /* signals to block during server calls */
 static int fd_socket = -1;  /* socket to exchange file descriptors with the server */
 static int terminal_lock;
+static pid_t server_pid;
 
 static RTL_CRITICAL_SECTION fd_cache_section;
 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
@@ -397,6 +398,13 @@ static int receive_fd( obj_handle_t *handle )
             {
                 if (cmsg->cmsg_level != SOL_SOCKET) continue;
                 if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
+#ifdef SCM_CREDENTIALS
+                else if (cmsg->cmsg_type == SCM_CREDENTIALS)
+                {
+                    struct ucred *ucred = (struct ucred *)CMSG_DATA(cmsg);
+                    server_pid = ucred->pid;
+                }
+#endif
             }
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
             if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
@@ -927,6 +935,7 @@ void server_init_process(void)
     obj_handle_t version;
     const char *env_socket = getenv( "WINESERVERSOCKET" );
 
+    server_pid = -1;
     if (env_socket)
     {
         fd_socket = atoi( env_socket );
@@ -948,6 +957,17 @@ void server_init_process(void)
     pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
 
     /* receive the first thread request fd on the main socket */
+#ifdef SO_PASSCRED
+    if (server_pid == -1)
+    {
+        int enable = 1;
+        setsockopt( fd_socket, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) );
+        ntdll_get_thread_data()->request_fd = receive_fd( &version );
+        enable = 0;
+        setsockopt( fd_socket, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) );
+    }
+    else
+#endif
     ntdll_get_thread_data()->request_fd = receive_fd( &version );
 
     if (version != SERVER_PROTOCOL_VERSION)
-- 
1.7.4.2

----------- следующая часть -----------
From 83c334392e76f494fa264d193d8c7920e1007e8e Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard на winehq.org>
Date: Thu, 30 Sep 2010 17:05:35 +0200
Subject: [eter-1.0.12 4/4] ntdll: Add a workaround for Ubuntu's stupid ptrace breakage.

---
 dlls/ntdll/server.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 23cb053..f1e2eb9 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -45,6 +45,9 @@
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #endif
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
 #endif
@@ -980,6 +983,10 @@ void server_init_process(void)
 #ifdef __APPLE__
     send_server_task_port();
 #endif
+#if defined(__linux__) && defined(HAVE_PRCTL)
+    /* work around Ubuntu's ptrace breakage */
+    if (server_pid != -1) prctl( 0x59616d61 /* PR_SET_PTRACER */, server_pid );
+#endif
 }
 
 
-- 
1.7.4.2



Подробная информация о списке рассылки Wine-patches