summaryrefslogtreecommitdiff
path: root/testing/xorg-server/xserver-1.11.2-record-crasher.patch
blob: 3af207bb96efa840f592c891cc26922920b8a785 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
From patchwork Tue Nov  8 18:22:13 2011
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: Save major/minor opcodes in ClientRec for RecordAReply
Date: Tue, 08 Nov 2011 18:22:13 -0000
From: Keith Packard <keithp@keithp.com>
X-Patchwork-Id: 7866
Message-Id: <1320776533-3120-1-git-send-email-keithp@keithp.com>
To: xorg-devel@lists.freedesktop.org

The record extension needs the major and minor opcodes in the reply
hook, but the request buffer may have been freed by the time the hook
is invoked. Saving the request major and minor codes as the request is
executed avoids fetching from the defunct request buffer.

This patch also eliminates the public MinorOpcodeOfRequest function,
making it static to dispatch. Usages of that function have been
replaced with direct access to the new ClientRec field.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Rami Ylimäki <rami.ylimaki@vincit.fi>

---
Here's what I was thinking of to fix this -- just record the major and
minor opcodes of the request in the ClientRec during Dispatch and then
using those fields in RecordAReply instead of fetching the discarded
request buffer.

This is entirely untested; I don't know how to make the old code break.

 Xext/security.c       |    4 +---
 Xext/xselinux_hooks.c |    4 ++--
 dix/dispatch.c        |   31 ++++++++++++++++++++++---------
 dix/extension.c       |   14 --------------
 include/dixstruct.h   |    1 +
 include/extension.h   |    2 --
 record/record.c       |    8 +++-----
 7 files changed, 29 insertions(+), 35 deletions(-)

[ fedora: technically this is an ABI breaker since it's changing ClientRec,
  but hopefully not in a way that matters.  If it does matter, easiest thing
  to do is have Record add a hook for XaceHookDispatch. - ajax ]

diff --git a/Xext/security.c b/Xext/security.c
index 08d8158..b0d82ab 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -148,9 +148,7 @@ SecurityLabelInitial(void)
 static _X_INLINE const char *
 SecurityLookupRequestName(ClientPtr client)
 {
-    int major = ((xReq *)client->requestBuffer)->reqType;
-    int minor = MinorOpcodeOfRequest(client);
-    return LookupRequestName(major, minor);
+    return LookupRequestName(client->majorOp, client->minorOp);
 }
 
 
diff --git a/Xext/xselinux_hooks.c b/Xext/xselinux_hooks.c
index f1d8e5d..0d4c9ab 100644
--- a/Xext/xselinux_hooks.c
+++ b/Xext/xselinux_hooks.c
@@ -263,8 +263,8 @@ SELinuxAudit(void *auditdata,
     if (client) {
 	REQUEST(xReq);
 	if (stuff) {
-	    major = stuff->reqType;
-	    minor = MinorOpcodeOfRequest(client);
+	    major = client->majorOp;
+	    minor = client->minorOp;
 	}
     }
     if (audit->id)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 6e33615..3600acd 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -337,7 +337,20 @@ DisableLimitedSchedulingLatency(void)
 	SmartScheduleLatencyLimited = 0;
 }
 
-#define MAJOROP ((xReq *)client->requestBuffer)->reqType
+static inline unsigned short
+MinorOpcodeOfRequest(ClientPtr client)
+{
+    unsigned char major;
+    ExtensionEntry *ext;
+
+    major = ((xReq *)client->requestBuffer)->reqType;
+    if (major < EXTENSION_BASE)
+	return 0;
+    ext = GetExtensionEntry(major);
+    if (!ext)
+	return 0;
+    return ext->MinorOpcode (client);
+}
 
 void
 Dispatch(void)
@@ -419,21 +432,23 @@ Dispatch(void)
 	        }
 
 		client->sequence++;
+		client->majorOp = ((xReq *)client->requestBuffer)->reqType;
+		client->minorOp = MinorOpcodeOfRequest(client);
 #ifdef XSERVER_DTRACE
-		XSERVER_REQUEST_START(LookupMajorName(MAJOROP), MAJOROP,
+		XSERVER_REQUEST_START(LookupMajorName(client->majorOp), client->majorOp,
 			      ((xReq *)client->requestBuffer)->length,
 			      client->index, client->requestBuffer);
 #endif
 		if (result > (maxBigRequestSize << 2))
 		    result = BadLength;
 		else {
-		    result = XaceHookDispatch(client, MAJOROP);
+		    result = XaceHookDispatch(client, client->majorOp);
 		    if (result == Success)
-			result = (* client->requestVector[MAJOROP])(client);
+			result = (* client->requestVector[client->majorOp])(client);
 		    XaceHookAuditEnd(client, result);
 		}
 #ifdef XSERVER_DTRACE
-		XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP,
+		XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), client->majorOp,
 			      client->sequence, client->index, result);
 #endif
 
@@ -444,8 +459,8 @@ Dispatch(void)
 		}
 		else if (result != Success)
 		{
-		    SendErrorToClient(client, MAJOROP,
-				      MinorOpcodeOfRequest(client),
+		    SendErrorToClient(client, client->majorOp,
+				      client->minorOp,
 				      client->errorValue, result);
 		    break;
 		}
@@ -466,8 +481,6 @@ Dispatch(void)
     SmartScheduleLatencyLimited = 0;
 }
 
-#undef MAJOROP
-
 static int  VendorRelease = VENDOR_RELEASE;
 static char *VendorString = VENDOR_NAME;
 
diff --git a/dix/extension.c b/dix/extension.c
index c7bbac5..b677cdb 100644
--- a/dix/extension.c
+++ b/dix/extension.c
@@ -228,20 +228,6 @@ StandardMinorOpcode(ClientPtr client)
     return ((xReq *)client->requestBuffer)->data;
 }
 
-unsigned short
-MinorOpcodeOfRequest(ClientPtr client)
-{
-    unsigned char major;
-
-    major = ((xReq *)client->requestBuffer)->reqType;
-    if (major < EXTENSION_BASE)
-	return 0;
-    major -= EXTENSION_BASE;
-    if (major >= NumExtensions)
-	return 0;
-    return (*extensions[major]->MinorOpcode)(client);
-}
-
 void
 CloseDownExtensions(void)
 {
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 6cc9614..0a85f40 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -122,6 +122,7 @@ typedef struct _Client {
     
     DeviceIntPtr clientPtr;
     ClientIdPtr  clientIds;
+    unsigned short majorOp, minorOp;
 }           ClientRec;
 
 /*
diff --git a/include/extension.h b/include/extension.h
index 29a11c3..9249951 100644
--- a/include/extension.h
+++ b/include/extension.h
@@ -52,8 +52,6 @@ _XFUNCPROTOBEGIN
 
 extern _X_EXPORT unsigned short StandardMinorOpcode(ClientPtr /*client*/);
 
-extern _X_EXPORT unsigned short MinorOpcodeOfRequest(ClientPtr /*client*/);
-
 extern _X_EXPORT Bool EnableDisableExtension(char *name, Bool enable);
 
 extern _X_EXPORT void EnableDisableExtensionError(char *name, Bool enable);
diff --git a/record/record.c b/record/record.c
index 68311ac..4a0fe23 100644
--- a/record/record.c
+++ b/record/record.c
@@ -546,7 +546,7 @@ RecordARequest(ClientPtr client)
 	    }
 	    else /* extension, check minor opcode */
 	    {
-		int minorop = MinorOpcodeOfRequest(client);
+		int minorop = client->minorOp;
 		int numMinOpInfo;
 		RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo;
 
@@ -603,12 +603,9 @@ RecordAReply(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
     RecordContextPtr pContext;
     RecordClientsAndProtocolPtr pRCAP;
     int eci;
-    int majorop;
     ReplyInfoRec *pri = (ReplyInfoRec *)calldata;
     ClientPtr client = pri->client;
-    REQUEST(xReq);
 
-    majorop = stuff->reqType;
     for (eci = 0; eci < numEnabledContexts; eci++)
     {
 	pContext = ppAllContexts[eci];
@@ -616,6 +613,7 @@ RecordAReply(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
 					  NULL);
 	if (pRCAP)
 	{
+	    int majorop = client->majorOp;
 	    if (pContext->continuedReply)
 	    {
 		RecordAProtocolElement(pContext, client, XRecordFromServer,
@@ -635,7 +633,7 @@ RecordAReply(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
 		}
 		else /* extension, check minor opcode */
 		{
-		    int minorop = MinorOpcodeOfRequest(client);
+		    int minorop = client->minorOp;
 		    int numMinOpInfo;
 		    RecordMinorOpPtr pMinorOpInfo = pRCAP->pReplyMinOpInfo;
 		    		    assert (pMinorOpInfo);