diff --git a/Xext/shm.c b/Xext/shm.c index 59def065b..76a48f461 100644 --- a/Xext/shm.c +++ b/Xext/shm.c @@ -1151,14 +1151,15 @@ ProcShmAttachFd(ClientPtr client) REQUEST(xShmAttachFdReq); struct stat statb; - SetReqFds(client, 1); REQUEST_SIZE_MATCH(xShmAttachFdReq); LEGAL_NEW_RESOURCE(stuff->shmseg, client); if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { client->errorValue = stuff->readOnly; return BadValue; } - fd = ReadFdFromClient(client); + fd = client->recv_fd_list[0]; + client->recv_fd_list[0] = -1; + if (fd < 0) return BadMatch; @@ -1462,7 +1463,6 @@ static int _X_COLD SProcShmAttachFd(ClientPtr client) { REQUEST(xShmAttachFdReq); - SetReqFds(client, 1); REQUEST_SIZE_MATCH(xShmAttachFdReq); swapl(&stuff->shmseg); return ProcShmAttachFd(client); diff --git a/dix/dispatch.c b/dix/dispatch.c index 72cd08750..95737ab7a 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -559,6 +559,14 @@ Dispatch(void) (*client->requestVector[client->majorOp]) (client); currentClient = NULL; } + +#if XTRANS_SEND_FDS + /* close down all unused passed fd's */ + for (int x=0; xrecv_fd_list[x]); + client->recv_fd_list[x] = -1; + } +#endif } if (!SmartScheduleSignalEnable) SmartScheduleTime = GetTimeInMillis(); diff --git a/dix/dixstruct_priv.h b/dix/dixstruct_priv.h index 0601448f5..37afad472 100644 --- a/dix/dixstruct_priv.h +++ b/dix/dixstruct_priv.h @@ -16,13 +16,6 @@ #include "dixstruct.h" #include -static inline void -SetReqFds(ClientPtr client, int req_fds) { - if (client->req_fds != 0 && req_fds != client->req_fds) - LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds); - client->req_fds = req_fds; -} - /* * Scheduling interface */ diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c index 2c1d5ca85..8e84f6470 100644 --- a/dri3/dri3_request.c +++ b/dri3/dri3_request.c @@ -191,7 +191,6 @@ proc_dri3_pixmap_from_buffer(ClientPtr client) CARD32 stride, offset; int rc; - SetReqFds(client, 1); REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); LEGAL_NEW_RESOURCE(stuff->pixmap, client); rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); @@ -220,7 +219,8 @@ proc_dri3_pixmap_from_buffer(ClientPtr client) } } - fd = ReadFdFromClient(client); + fd = client->recv_fd_list[0]; + client->recv_fd_list[0] = -1; if (fd < 0) return BadValue; @@ -309,7 +309,6 @@ proc_dri3_fence_from_fd(ClientPtr client) int fd; int status; - SetReqFds(client, 1); REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); LEGAL_NEW_RESOURCE(stuff->fence, client); @@ -317,7 +316,8 @@ proc_dri3_fence_from_fd(ClientPtr client) if (status != Success) return status; - fd = ReadFdFromClient(client); + fd = client->recv_fd_list[0]; + client->recv_fd_list[0] = -1; if (fd < 0) return BadValue; @@ -434,7 +434,6 @@ proc_dri3_pixmap_from_buffers(ClientPtr client) int rc; int i; - SetReqFds(client, stuff->num_buffers); REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq); LEGAL_NEW_RESOURCE(stuff->pixmap, client); rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); @@ -470,7 +469,7 @@ proc_dri3_pixmap_from_buffers(ClientPtr client) } for (i = 0; i < stuff->num_buffers; i++) { - fds[i] = ReadFdFromClient(client); + fds[i] = client->recv_fd_list[i]; if (fds[i] < 0) { while (--i >= 0) close(fds[i]); @@ -609,7 +608,6 @@ proc_dri3_import_syncobj(ClientPtr client) int fd; int status; - SetReqFds(client, 1); REQUEST_SIZE_MATCH(xDRI3ImportSyncobjReq); LEGAL_NEW_RESOURCE(stuff->syncobj, client); @@ -620,7 +618,8 @@ proc_dri3_import_syncobj(ClientPtr client) screen = drawable->pScreen; - fd = ReadFdFromClient(client); + fd = client->recv_fd_list[0]; + client->recv_fd_list[0] = -1; if (fd < 0) return BadValue; diff --git a/include/dixstruct.h b/include/dixstruct.h index 3607ea88a..c16d00f7d 100644 --- a/include/dixstruct.h +++ b/include/dixstruct.h @@ -73,6 +73,9 @@ typedef struct _saveSet { #define SaveSetAssignToRoot(ss,tr) ((ss).toRoot = (tr)) #define SaveSetAssignMap(ss,m) ((ss).map = (m)) +/* currently largest one in use is 4 */ +#define MAX_CLIENT_RECV_FD 8 + typedef struct _Client { void *requestBuffer; void *osPrivate; /* for OS layer, including scheduler */ @@ -110,7 +113,9 @@ typedef struct _Client { DeviceIntPtr clientPtr; ClientIdPtr clientIds; - int req_fds; + + int recv_fd_count; + int recv_fd_list[MAX_CLIENT_RECV_FD]; } ClientRec; typedef struct _WorkQueue { diff --git a/include/os.h b/include/os.h index 0c81818b0..ccd77afb8 100644 --- a/include/os.h +++ b/include/os.h @@ -90,8 +90,6 @@ extern _X_EXPORT Bool WaitForSomething(Bool clients_are_ready); extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ ); -extern _X_EXPORT int ReadFdFromClient(ClientPtr client); - extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close); extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ , diff --git a/os/io.c b/os/io.c index 43c4e5d30..066b1fd52 100644 --- a/os/io.c +++ b/os/io.c @@ -254,14 +254,6 @@ ReadRequestFromClient(ClientPtr client) oc->input = oci; } -#if XTRANS_SEND_FDS - /* Discard any unused file descriptors */ - while (client->req_fds > 0) { - int req_fd = ReadFdFromClient(client); - if (req_fd >= 0) - close(req_fd); - } -#endif /* advance to start of next request */ oci->bufptr += oci->lenLastReq; @@ -466,25 +458,23 @@ ReadRequestFromClient(ClientPtr client) client->index, req->reqType, req->data, req->length); } #endif - return needed; -} - -int -ReadFdFromClient(ClientPtr client) -{ - int fd = -1; + /* read the passed fds into Client struct */ + client->recv_fd_count = 0; #if XTRANS_SEND_FDS - if (client->req_fds > 0) { - OsCommPtr oc = (OsCommPtr) client->osPrivate; - - --client->req_fds; - fd = _XSERVTransRecvFd(oc->trans_conn); - } else - LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n"); + for (;((client->recv_fd_count < MAX_CLIENT_RECV_FD) && + (client->recv_fd_list[client->recv_fd_count] = _XSERVTransRecvFd(oc->trans_conn)) > 0); + client->recv_fd_count++) {} + // just in case somebody sent a massive number of fd's + int _fd = -1; + while ((_fd = _XSERVTransRecvFd(oc->trans_conn)) > 0) + close(_fd); #endif - return fd; + for (int x=client->recv_fd_count; xrecv_fd_list[x] = -1; + + return needed; } int