Attachment #492083: Stop untrusted script from QIing to non-ClassInfo interfaces for bug #605271

View | Details | Raw Unified | Return to bug 605271
Collapse All | Expand All

(-)a/content/base/src/nsGenericElement.cpp (+16 lines)
Line     Link Here 
 Lines 4490-4495    Link Here 
4490
                                                        nsIContent,
4490
                                                        nsIContent,
4491
                                                        nsNodeUtils::LastRelease(this))
4491
                                                        nsNodeUtils::LastRelease(this))
4492
4492
4493
PRBool
4494
nsGenericElement::ImplementsXBLIface(REFNSIID aIID)
4495
{
4496
  nsIDocument *document = GetOwnerDoc();
4497
  if (!document) {
4498
    return PR_FALSE;
4499
  }
4500
4501
  nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
4502
  if (!binding) {
4503
    return PR_FALSE;
4504
  }
4505
4506
  return binding->ImplementsInterface(aIID);
4507
}
4508
4493
nsresult
4509
nsresult
4494
nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
4510
nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
4495
{
4511
{
(-)a/content/base/src/nsGenericElement.h (+1 lines)
Line     Link Here 
 Lines 337-342    Link Here 
337
   * get an interface for this element.
337
   * get an interface for this element.
338
   */
338
   */
339
  nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
339
  nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
340
  PRBool ImplementsXBLIface(REFNSIID aIID);
340
341
341
  // nsINode interface methods
342
  // nsINode interface methods
342
  virtual PRUint32 GetChildCount() const;
343
  virtual PRUint32 GetChildCount() const;
(-)a/content/base/test/test_bug166235.html (+2 lines)
Line     Link Here 
 Lines 67-72    Link Here 
67
  function testPasteText(expected, test) {
67
  function testPasteText(expected, test) {
68
    textarea.value="";
68
    textarea.value="";
69
    textarea.focus();
69
    textarea.focus();
70
    // To QI to non-ClassInfo interfaces we must assert privileges
71
    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
70
    textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
72
    textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
71
            .editor.paste(1);
73
            .editor.paste(1);
72
    is(textarea.value, expected, test + ": textarea paste");
74
    is(textarea.value, expected, test + ": textarea paste");
(-)a/content/base/test/test_copypaste.html (+2 lines)
Line     Link Here 
 Lines 104-109    Link Here 
104
  function testPasteText(expected) {
104
  function testPasteText(expected) {
105
    textarea.value="";
105
    textarea.value="";
106
    textarea.focus();
106
    textarea.focus();
107
    // To QI to non-ClassInfo interfaces we must assert privileges
108
    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
107
    textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
109
    textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
108
            .editor.paste(1);
110
            .editor.paste(1);
109
    is(textarea.value, expected, "value of the textarea after the paste");
111
    is(textarea.value, expected, "value of the textarea after the paste");
(-)a/content/html/content/test/Makefile.in (+1 lines)
Line     Link Here 
 Lines 241-246    Link Here 
241
		test_bug607145.html \
241
		test_bug607145.html \
242
		test_bug601061.html \
242
		test_bug601061.html \
243
		test_bug596511.html \
243
		test_bug596511.html \
244
		test_bug605271.html \
244
		reflect.js \
245
		reflect.js \
245
		$(NULL)
246
		$(NULL)
246
247
(-)a/content/html/content/test/test_bug388558.html (-1 / +2 lines)
Line     Link Here 
 Lines 24-30    Link Here 
24
var textareaChange = 0;
24
var textareaChange = 0;
25
25
26
function testUserInput() {
26
function testUserInput() {
27
  netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserWrite');
27
  // To QI to non-ClassInfo interfaces we must assert privileges
28
  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
28
  var input = document.getElementById("input");
29
  var input = document.getElementById("input");
29
  var textarea = document.getElementById("textarea");
30
  var textarea = document.getElementById("textarea");
30
31
(-)a/content/html/content/test/test_bug389797.html (-5 / +80 lines)
Line     Link Here 
 Lines 23-28    Link Here 
23
var classInfos = {};
23
var classInfos = {};
24
var interfaces = {};
24
var interfaces = {};
25
var interfacesNonClassinfo = {};
25
var interfacesNonClassinfo = {};
26
var interfacesNonDOM = {};
26
27
27
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
28
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
28
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
29
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
 Lines 45-55    Link Here 
45
      "nsIDOMNodeSelector" ];
46
      "nsIDOMNodeSelector" ];
46
47
47
  // Some interfaces don't appear in classinfo because other interfaces that
48
  // Some interfaces don't appear in classinfo because other interfaces that
48
  // inherit from them do.
49
  // inherit from them do. These are visible to unprivileged script.
49
  interfacesNonClassinfo[aTagName] =
50
  interfacesNonClassinfo[aTagName] =
50
    [ "nsIDOMNode",
51
    [ "nsIDOMNode",
51
      "nsIDOMElement",
52
      "nsIDOMElement"];
52
      "nsIDOM3EventTarget",
53
54
  // Some interfaces don't appear in classinfo because they are implementation
55
  // details of the underlying XPCOM objects. These are not visible to
56
  // unprivileged script.
57
  interfacesNonDOM[aTagName] = 
58
    [ "nsIDOM3EventTarget",
53
      "nsISupportsWeakReference" ];
59
      "nsISupportsWeakReference" ];
54
60
55
  var interfaceName = "nsIDOM" + getClassName(aTagName);
61
  var interfaceName = "nsIDOM" + getClassName(aTagName);
 Lines 76-82    Link Here 
76
82
77
  if (arguments.length > 3) {
83
  if (arguments.length > 3) {
78
    for (i = 0; i < arguments[3].length; ++i) {
84
    for (i = 0; i < arguments[3].length; ++i) {
79
      interfacesNonClassinfo[aTagName].push(arguments[3][i]);
85
      interfacesNonDOM[aTagName].push(arguments[3][i]);
80
    }
86
    }
81
  }
87
  }
82
}
88
}
 Lines 247-252    Link Here 
247
  return "<" + aTag + ">";
253
  return "<" + aTag + ">";
248
}
254
}
249
255
256
netscape.security.PrivilegeManager.revertPrivilege('UniversalXPConnect');
257
250
for each (var tag in allTags) {
258
for each (var tag in allTags) {
251
  var node = document.createElement(tag);
259
  var node = document.createElement(tag);
252
260
 Lines 272-279    Link Here 
272
       tagName(tag) + " does not QI to " + iface);
280
       tagName(tag) + " does not QI to " + iface);
273
  }
281
  }
274
282
283
  // Check that each node doesn't QI to non-DOM things 
284
  for each (var iface in interfacesNonDOM[tag]) {
285
    is(iface in Components.interfaces, true,
286
       iface + " not in Components.interfaces");
287
    is(node instanceof Components.interfaces[iface], false,
288
       tagName(tag) + " should not QI to " + iface);
289
  }
290
}
291
292
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
293
for each (var tag in allTags) {
294
  var node = document.createElement(tag);
295
296
  // Have to use the proto's toString(), since HTMLAnchorElement and company
297
  // override toString().
298
  var nodeString = HTMLElement.prototype.toString.apply(node);
299
300
  // Debug builds have extra info, so chop off after "Element" if it's followed
301
  // by ' ' or ']'
302
  nodeString = nodeString.replace(/Element[\] ].*/, "Element");
303
304
  // Check that each node doesn't QI to non-DOM things, except when we have privs
305
  for each (var iface in interfacesNonDOM[tag]) {
306
    is(iface in Components.interfaces, true,
307
       iface + " not in Components.interfaces");
308
    is(node instanceof Components.interfaces[iface], true,
309
       tagName(tag) + " should QI to " + iface + " from privileged script");
310
  }
311
275
  // Now see what classinfo reports
312
  // Now see what classinfo reports
276
  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
277
  var nodeClassInfo = node.QueryInterface(Components.interfaces.nsIClassInfo);
313
  var nodeClassInfo = node.QueryInterface(Components.interfaces.nsIClassInfo);
278
  var count = {};
314
  var count = {};
279
  var classInfoInterfaces =
315
  var classInfoInterfaces =
 Lines 294-299    Link Here 
294
          iface);
330
          iface);
295
  }
331
  }
296
}
332
}
333
334
netscape.security.PrivilegeManager.revertPrivilege('UniversalXPConnect');
335
336
// Finally, run all of the non privileged checks again to make sure that
337
// tearoffs were not cached inappropriately.
338
for each (var tag in allTags) {
339
  var node = document.createElement(tag);
340
341
  // Have to use the proto's toString(), since HTMLAnchorElement and company
342
  // override toString().
343
  var nodeString = HTMLElement.prototype.toString.apply(node);
344
345
  // Debug builds have extra info, so chop off after "Element" if it's followed
346
  // by ' ' or ']'
347
  nodeString = nodeString.replace(/Element[\] ].*/, "Element");
348
349
  var classInfoString = getClassName(tag);
350
  is(nodeString, "[object " + classInfoString,
351
     "Unexpected classname for " + tagName(tag));
352
  is(node instanceof window[classInfoString], true,
353
     tagName(tag) + " not an instance of " + classInfos[tag]);
354
355
  // Check that each node QIs to all the things we expect it to QI to
356
  for each (var iface in interfaces[tag].concat(interfacesNonClassinfo[tag])) {
357
    is(iface in Components.interfaces, true,
358
       iface + " not in Components.interfaces");
359
    is(node instanceof Components.interfaces[iface], true,
360
       tagName(tag) + " does not QI to " + iface);
361
  }
362
363
  // Check that each node doesn't QI to non-DOM things 
364
  for each (var iface in interfacesNonDOM[tag]) {
365
    is(iface in Components.interfaces, true,
366
       iface + " not in Components.interfaces");
367
    is(node instanceof Components.interfaces[iface], false,
368
       tagName(tag) + " should not QI to " + iface);
369
  }
370
}
371
297
</script>
372
</script>
298
</pre>
373
</pre>
299
</body>
374
</body>
(-)a/content/html/content/test/test_bug605271.html (+35 lines)
Line     Link Here 
Line 0    Link Here 
1
<!DOCTYPE HTML>
2
<html>
3
<!--
4
https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}
5
-->
6
<head>
7
  <title>Test for Bug {BUGNUMBER}</title>
8
  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
9
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
10
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
11
</head>
12
<body>
13
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}">Mozilla Bug {BUGNUMBER}</a>
14
<p id="display"></p>
15
<div id="content" style="display: none">
16
  
17
</div>
18
<pre id="test">
19
<script class="testbody" type="text/javascript">
20
21
/** Test for Bug {BUGNUMBER} **/
22
var elem = $("display");
23
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
24
elem.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
25
elem.addGroupedEventListener; // force this to be resolved
26
netscape.security.PrivilegeManager.revertPrivilege('UniversalXPConnect');
27
ok(!(elem instanceof Components.interfaces.nsIDOM3EventTarget),
28
   "tearoff crossed privilege scope");
29
is(elem.addGroupedEventListener, undefined, "tearoff crossed privilege scope");
30
is(Object.keys(elem), "", "tearoff crossed privilege scope");
31
32
</script>
33
</pre>
34
</body>
35
</html>
(-)a/dom/base/nsDOMClassInfo.cpp (-1 / +55 lines)
Line     Link Here 
 Lines 533-538    Link Here 
533
533
534
#define ELEMENT_SCRIPTABLE_FLAGS                                              \
534
#define ELEMENT_SCRIPTABLE_FLAGS                                              \
535
  ((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) |   \
535
  ((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) |   \
536
   nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY_NOPRIVS |                      \
536
   nsIXPCScriptable::WANT_POSTCREATE |                                        \
537
   nsIXPCScriptable::WANT_POSTCREATE |                                        \
537
   nsIXPCScriptable::WANT_ENUMERATE)
538
   nsIXPCScriptable::WANT_ENUMERATE)
538
539
 Lines 4730-4735    Link Here 
4730
                          &unused);
4731
                          &unused);
4731
}
4732
}
4732
4733
4734
PRBool
4735
nsDOMClassInfo::ShouldReflectNonClassInfoIface(nsISupports* aObj,
4736
                                               REFNSIID aIID)
4737
{
4738
  return PR_FALSE;
4739
}
4740
4733
// static
4741
// static
4734
nsIClassInfo *
4742
nsIClassInfo *
4735
NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
4743
NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
 Lines 7722-7727    Link Here 
7722
  return PR_TRUE;
7730
  return PR_TRUE;
7723
}
7731
}
7724
7732
7733
// If the prop is on this object (classinfo interfaces are on the proto)
7734
// and it isn't exposed through XBL, veto access to unprivileged callers.
7735
NS_IMETHODIMP
7736
nsElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
7737
                         JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
7738
{
7739
  if (!wrapper)
7740
    return NS_OK; // Not interested in slim wrappers
7741
7742
  nsISupports* native = wrapper->Native();
7743
  nsGenericElement *element = static_cast<nsGenericElement*>(native);
7744
  nsCOMPtr<nsIInterfaceInfo> iInfo;
7745
  nsresult rv = wrapper->FindInterfaceWithMember(id, getter_AddRefs(iInfo));
7746
  NS_ENSURE_SUCCESS(rv, rv);
7747
7748
  if (!iInfo)
7749
    return NS_OK;
7750
7751
  const nsIID* iid;
7752
  rv = iInfo->GetIIDShared(&iid);
7753
  NS_ENSURE_SUCCESS(rv, rv);
7754
7755
  if (element->ImplementsXBLIface(*iid))
7756
    return NS_OK; // Allow this to proceed
7757
7758
  // Otherwise, veto if appropriate
7759
  if (!nsContentUtils::IsCallerTrustedForCapability("UniversalXPConnect")) {
7760
    *vp = JSVAL_VOID;
7761
    *_retval = JS_TRUE;
7762
    return NS_SUCCESS_I_DID_SOMETHING;
7763
  }
7764
7765
  return nsNodeSH::GetProperty(wrapper, cx, obj, id, vp, _retval);
7766
}
7767
7725
NS_IMETHODIMP
7768
NS_IMETHODIMP
7726
nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
7769
nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
7727
                       JSObject *globalObj, JSObject **parentObj)
7770
                       JSObject *globalObj, JSObject **parentObj)
 Lines 7880-7886    Link Here 
7880
  
7923
  
7881
  return NS_OK;
7924
  return NS_OK;
7882
}
7925
}
7883
  
7926
7927
PRBool
7928
nsElementSH::ShouldReflectNonClassInfoIface(nsISupports* aObj, REFNSIID aIID)
7929
{
7930
  nsCOMPtr<Element> element = do_QueryInterface(aObj);
7931
  if (!element) {
7932
    return PR_FALSE;
7933
  }
7934
7935
  nsGenericElement* object = static_cast<nsGenericElement*>(element.get());
7936
  return object->ImplementsXBLIface(aIID);
7937
}
7884
7938
7885
// Generic array scriptable helper.
7939
// Generic array scriptable helper.
7886
7940
(-)a/dom/base/nsDOMClassInfo.h (+5 lines)
Line     Link Here 
 Lines 702-707    Link Here 
702
                        JSObject *obj);
702
                        JSObject *obj);
703
  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
703
  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
704
                       JSObject *obj, PRBool *_retval);
704
                       JSObject *obj, PRBool *_retval);
705
  NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
706
                         JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
707
708
  virtual PRBool ShouldReflectNonClassInfoIface(nsISupports *aObj,
709
                                                REFNSIID aIID);
705
710
706
  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
711
  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
707
  {
712
  {
(-)a/js/src/xpconnect/idl/nsIXPCScriptable.idl (-2 / +15 lines)
Line     Link Here 
 Lines 115-120    Link Here 
115
    const PRUint32 DONT_REFLECT_INTERFACE_NAMES     = 1 << 27;
115
    const PRUint32 DONT_REFLECT_INTERFACE_NAMES     = 1 << 27;
116
    const PRUint32 WANT_EQUALITY                    = 1 << 28;
116
    const PRUint32 WANT_EQUALITY                    = 1 << 28;
117
    const PRUint32 WANT_OUTER_OBJECT                = 1 << 29;
117
    const PRUint32 WANT_OUTER_OBJECT                = 1 << 29;
118
    // Just like CLASSINFO_INTERFACES_ONLY, but code with
119
    // UniversalXPConnect can QI through
120
    const PRUInt32 CLASSINFO_INTERFACES_ONLY_NOPRIVS= 1 << 30;
118
121
119
    // The high order bit is RESERVED for consumers of these flags. 
122
    // The high order bit is RESERVED for consumers of these flags. 
120
    // No implementor of this interface should ever return flags 
123
    // No implementor of this interface should ever return flags 
 Lines 197-202    Link Here 
197
                            in JSContextPtr cx, in JSObjectPtr obj);
200
                            in JSContextPtr cx, in JSObjectPtr obj);
198
201
199
    void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
202
    void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
203
204
205
    [notxpcom] PRBool ShouldReflectNonClassInfoIface(in nsISupports obj,
206
                                                     in nsIIDRef iid);
200
};
207
};
201
208
202
%{ C++
209
%{ C++
 Lines 204-211    Link Here 
204
#include "nsAutoPtr.h"
211
#include "nsAutoPtr.h"
205
212
206
#define NS_XPCCLASSINFO_IID \
213
#define NS_XPCCLASSINFO_IID \
207
{ 0x9a5b0342, 0x0f70, 0x4d31, \
214
{ 0x56355458, 0x109f, 0x4148, \
208
 { 0xb7, 0xd7, 0x29, 0x68, 0xa5, 0x70, 0x4b, 0xd8 } }
215
 { 0xa9, 0x92, 0x98, 0x93, 0x3e, 0x28, 0xca, 0xa2 } }
209
216
210
class NS_NO_VTABLE nsXPCClassInfo : public nsIClassInfo,
217
class NS_NO_VTABLE nsXPCClassInfo : public nsIClassInfo,
211
                                    public nsIXPCScriptable
218
                                    public nsIXPCScriptable
 Lines 219-224    Link Here 
219
  virtual void PreserveWrapper(nsISupports *aNative) = 0;
226
  virtual void PreserveWrapper(nsISupports *aNative) = 0;
220
227
221
  virtual PRUint32 GetInterfacesBitmap() = 0;
228
  virtual PRUint32 GetInterfacesBitmap() = 0;
229
230
  virtual PRBool ShouldReflectNonClassInfoIface(nsISupports* aObj,
231
                                                REFNSIID aIID)
232
  {
233
    return PR_FALSE;
234
  }
222
};
235
};
223
236
224
NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCClassInfo, NS_XPCCLASSINFO_IID)
237
NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCClassInfo, NS_XPCCLASSINFO_IID)
(-)a/js/src/xpconnect/idl/nsIXPConnect.idl (+4 lines)
Line     Link Here 
 Lines 81-86    Link Here 
81
/***************************************************************************/
81
/***************************************************************************/
82
#define GENERATE_XPC_FAILURE(x) \
82
#define GENERATE_XPC_FAILURE(x) \
83
            (NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCONNECT,x))
83
            (NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCONNECT,x))
84
#define GENERATE_XPC_SUCCESS(x) \
85
            (NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,x))
84
86
85
#define NS_ERROR_XPC_NOT_ENOUGH_ARGS                   GENERATE_XPC_FAILURE( 1)
87
#define NS_ERROR_XPC_NOT_ENOUGH_ARGS                   GENERATE_XPC_FAILURE( 1)
86
#define NS_ERROR_XPC_NEED_OUT_OBJECT                   GENERATE_XPC_FAILURE( 2)
88
#define NS_ERROR_XPC_NEED_OUT_OBJECT                   GENERATE_XPC_FAILURE( 2)
 Lines 136-141    Link Here 
136
#define NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN            GENERATE_XPC_FAILURE(52)
138
#define NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN            GENERATE_XPC_FAILURE(52)
137
#define NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL    GENERATE_XPC_FAILURE(53)
139
#define NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL    GENERATE_XPC_FAILURE(53)
138
140
141
#define NS_SUCCESS_XPC_DONT_CACHE_TEAROFF              GENERATE_XPC_SUCCESS( 1)
142
139
#ifdef XPC_IDISPATCH_SUPPORT
143
#ifdef XPC_IDISPATCH_SUPPORT
140
// IDispatch support related errors
144
// IDispatch support related errors
141
#define NS_ERROR_XPC_COM_UNKNOWN                       GENERATE_XPC_FAILURE(54)
145
#define NS_ERROR_XPC_COM_UNKNOWN                       GENERATE_XPC_FAILURE(54)
(-)a/js/src/xpconnect/public/xpc_map_end.h (+7 lines)
Line     Link Here 
 Lines 56-61    Link Here 
56
    return NS_OK;
56
    return NS_OK;
57
}
57
}
58
58
59
PRBool
60
XPC_MAP_CLASSNAME::ShouldReflectNonClassInfoIface(nsISupports* aObj,
61
                                                  REFNSIID aIID)
62
{
63
    return PR_FALSE;
64
}
65
59
/**************************************************************/
66
/**************************************************************/
60
67
61
NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags)
68
NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags)
(-)a/js/src/xpconnect/src/xpcinlines.h (-1 / +2 lines)
Line     Link Here 
 Lines 686-692    Link Here 
686
inline JSBool
686
inline JSBool
687
XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid)
687
XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid)
688
{
688
{
689
    return nsnull != GetSet()->FindInterfaceWithIID(iid);
689
    XPCNativeInterface* iface = GetSet()->FindInterfaceWithIID(iid);
690
    return nsnull != iface && !iface->IsUnsafe();
690
}
691
}
691
692
692
inline void
693
inline void
(-)a/js/src/xpconnect/src/xpcprivate.h (-1 / +21 lines)
Line     Link Here 
 Lines 1749-1760    Link Here 
1749
    void DebugDump(PRInt16 depth);
1749
    void DebugDump(PRInt16 depth);
1750
1750
1751
#define XPC_NATIVE_IFACE_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
1751
#define XPC_NATIVE_IFACE_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
1752
#define XPC_NATIVE_IFACE_NOT_SAFE  ((PRUint16)JS_BIT(14))
1752
1753
1753
    void Mark()     {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
1754
    void Mark()     {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
1754
    void Unmark()   {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
1755
    void Unmark()   {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
1755
    JSBool IsMarked() const
1756
    JSBool IsMarked() const
1756
                    {return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
1757
                    {return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
1757
1758
1759
    void MarkUnsafe() {mMemberCount |= XPC_NATIVE_IFACE_NOT_SAFE;}
1760
    void UnmarkUnsafe() {mMemberCount &= ~XPC_NATIVE_IFACE_NOT_SAFE;}
1761
    JSBool IsUnsafe() const
1762
    {return 0 != (mMemberCount & XPC_NATIVE_IFACE_NOT_SAFE);}
1763
1758
    // NOP. This is just here to make the AutoMarkingPtr code compile.
1764
    // NOP. This is just here to make the AutoMarkingPtr code compile.
1759
    inline void TraceJS(JSTracer* trc) {}
1765
    inline void TraceJS(JSTracer* trc) {}
1760
    inline void AutoTrace(JSTracer* trc) {}
1766
    inline void AutoTrace(JSTracer* trc) {}
 Lines 1988-1993    Link Here 
1988
    JSBool AllowPropModsToPrototype()     GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
1994
    JSBool AllowPropModsToPrototype()     GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
1989
    JSBool DontSharePrototype()           GET_IT(DONT_SHARE_PROTOTYPE)
1995
    JSBool DontSharePrototype()           GET_IT(DONT_SHARE_PROTOTYPE)
1990
    JSBool DontReflectInterfaceNames()    GET_IT(DONT_REFLECT_INTERFACE_NAMES)
1996
    JSBool DontReflectInterfaceNames()    GET_IT(DONT_REFLECT_INTERFACE_NAMES)
1997
    JSBool ClassInfoInterfacesOnlyNoPrivs() GET_IT(CLASSINFO_INTERFACES_ONLY_NOPRIVS)
1991
1998
1992
#undef GET_IT
1999
#undef GET_IT
1993
};
2000
};
 Lines 2087-2092    Link Here 
2087
2094
2088
    void Mark() {if(mShared) mShared->Mark();}
2095
    void Mark() {if(mShared) mShared->Mark();}
2089
2096
2097
    PRBool ShouldReflectNonClassInfoIface(nsISupports* aObj, REFNSIID aIID)
2098
    {
2099
        return mCallback->ShouldReflectNonClassInfoIface(aObj, aIID);
2100
    }
2101
2090
protected:
2102
protected:
2091
    XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
2103
    XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
2092
                            XPCNativeScriptableShared* shared = nsnull)
2104
                            XPCNativeScriptableShared* shared = nsnull)
 Lines 2368-2374    Link Here 
2368
    void JSObjectFinalized() {SetJSObject(nsnull);}
2380
    void JSObjectFinalized() {SetJSObject(nsnull);}
2369
2381
2370
    XPCWrappedNativeTearOff()
2382
    XPCWrappedNativeTearOff()
2371
        : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {}
2383
        : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull), mUnsafe(PR_FALSE)
2384
    {}
2372
    ~XPCWrappedNativeTearOff();
2385
    ~XPCWrappedNativeTearOff();
2373
2386
2374
    // NOP. This is just here to make the AutoMarkingPtr code compile.
2387
    // NOP. This is just here to make the AutoMarkingPtr code compile.
 Lines 2379-2384    Link Here 
2379
    void Unmark()     {mJSObject = (JSObject*)(((jsword)mJSObject) & ~1);}
2392
    void Unmark()     {mJSObject = (JSObject*)(((jsword)mJSObject) & ~1);}
2380
    JSBool IsMarked() const {return (JSBool)(((jsword)mJSObject) & 1);}
2393
    JSBool IsMarked() const {return (JSBool)(((jsword)mJSObject) & 1);}
2381
2394
2395
    void MarkUnsafe() {mUnsafe = PR_TRUE;}
2396
    PRBool IsUnsafe() const {return mUnsafe;}
2397
2382
#ifdef XPC_IDISPATCH_SUPPORT
2398
#ifdef XPC_IDISPATCH_SUPPORT
2383
    enum JSObject_flags
2399
    enum JSObject_flags
2384
    {
2400
    {
 Lines 2397-2402    Link Here 
2397
    XPCNativeInterface* mInterface;
2413
    XPCNativeInterface* mInterface;
2398
    nsISupports*        mNative;
2414
    nsISupports*        mNative;
2399
    JSObject*           mJSObject;
2415
    JSObject*           mJSObject;
2416
    PRBool              mUnsafe;
2400
};
2417
};
2401
2418
2402
/***********************************************/
2419
/***********************************************/
 Lines 2772-2777    Link Here 
2772
2789
2773
    JSBool ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface);
2790
    JSBool ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface);
2774
2791
2792
    nsresult ShouldAllowQI(nsISupports* aIdentity,
2793
                           XPCNativeInterface* aInterface);
2794
2775
    nsresult InitTearOff(XPCCallContext& ccx,
2795
    nsresult InitTearOff(XPCCallContext& ccx,
2776
                         XPCWrappedNativeTearOff* aTearOff,
2796
                         XPCWrappedNativeTearOff* aTearOff,
2777
                         XPCNativeInterface* aInterface,
2797
                         XPCNativeInterface* aInterface,
(-)a/js/src/xpconnect/src/xpcwrappednative.cpp (-13 / +65 lines)
Line     Link Here 
 Lines 1066-1071    Link Here 
1066
                     "Can't set DONT_SHARE_PROTOTYPE on an instance scriptable "
1066
                     "Can't set DONT_SHARE_PROTOTYPE on an instance scriptable "
1067
                     "without also setting it on the class scriptable (if present and shared)");
1067
                     "without also setting it on the class scriptable (if present and shared)");
1068
1068
1069
        NS_ASSERTION(!(sciWrapper.GetFlags().ClassInfoInterfacesOnlyNoPrivs() &&
1070
                        !sciProto.GetFlags().ClassInfoInterfacesOnlyNoPrivs() &&
1071
                        sciProto.GetCallback()),
1072
                     "Can't set CLASSINFO_INTERFACES_ONLY_NOPRIVS on an instance scriptable "
1073
                     "without also setting it on the class scriptable (if present and shared)");
1074
1069
        return sciWrapper;
1075
        return sciWrapper;
1070
    }
1076
    }
1071
1077
 Lines 1826-1831    Link Here 
1826
        {
1832
        {
1827
            if(to->GetInterface() == aInterface)
1833
            if(to->GetInterface() == aInterface)
1828
            {
1834
            {
1835
                if(to->IsUnsafe())
1836
                    continue; // Don't reuse an unsafe tearoff
1837
1829
                if(needJSObject && !to->GetJSObject())
1838
                if(needJSObject && !to->GetJSObject())
1830
                {
1839
                {
1831
                    AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
1840
                    AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to);
 Lines 1870-1875    Link Here 
1870
        to->Unmark();
1879
        to->Unmark();
1871
        if(NS_FAILED(rv))
1880
        if(NS_FAILED(rv))
1872
            to = nsnull;
1881
            to = nsnull;
1882
        if (rv == NS_SUCCESS_XPC_DONT_CACHE_TEAROFF)
1883
            to->MarkUnsafe();
1873
    }
1884
    }
1874
1885
1875
return_result:
1886
return_result:
 Lines 1880-1885    Link Here 
1880
}
1891
}
1881
1892
1882
nsresult
1893
nsresult
1894
XPCWrappedNative::ShouldAllowQI(nsISupports* aIdentity,
1895
                                XPCNativeInterface* aInterface)
1896
{
1897
    if(!mScriptableInfo)
1898
        return NS_OK;
1899
1900
    // Does the scriptable helper say ClassInfo only for everyone?
1901
    if (mScriptableInfo->GetFlags().ClassInfoInterfacesOnly() &&
1902
        // NB: If the interface is Unsafe then we can't rely on it being in
1903
        // the set as a test of whether this is safe or not.
1904
        (aInterface->IsUnsafe() ||
1905
         (!mSet->HasInterface(aInterface) &&
1906
          !mSet->HasInterfaceWithAncestor(aInterface))) &&
1907
        !mScriptableInfo->ShouldReflectNonClassInfoIface(aIdentity,
1908
                                                         *aInterface->GetIID()))
1909
    {
1910
        // Don't even try the QI
1911
        return NS_ERROR_NO_INTERFACE;
1912
    }
1913
1914
    PRBool shouldRestrictTearoff = PR_FALSE;
1915
    // Or for non-privileged callers when the caller is non-privileged?
1916
    if (mScriptableInfo->GetFlags().ClassInfoInterfacesOnlyNoPrivs() &&
1917
        // NB: If the interface is Unsafe then we can't rely on it being in
1918
        // the set as a test of whether this is safe or not.
1919
        (aInterface->IsUnsafe() ||
1920
         (!mSet->HasInterface(aInterface) &&
1921
          !mSet->HasInterfaceWithAncestor(aInterface))) &&
1922
        !mScriptableInfo->ShouldReflectNonClassInfoIface(aIdentity,
1923
                                                         *aInterface->GetIID()) &&
1924
        (!NS_SUCCEEDED(XPCWrapper::GetSecurityManager()->
1925
                       IsCapabilityEnabled("UniversalXPConnect",
1926
                                           &shouldRestrictTearoff)) ||
1927
         !shouldRestrictTearoff))
1928
    {
1929
        // Don't even try the QI
1930
        return NS_ERROR_NO_INTERFACE;
1931
    }
1932
1933
    // Otherwise, try the QI, but be careful with the result tearoff if necessary
1934
    return shouldRestrictTearoff ? NS_SUCCESS_XPC_DONT_CACHE_TEAROFF : NS_OK;
1935
}
1936
1937
nsresult
1883
XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
1938
XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
1884
                              XPCWrappedNativeTearOff* aTearOff,
1939
                              XPCWrappedNativeTearOff* aTearOff,
1885
                              XPCNativeInterface* aInterface,
1940
                              XPCNativeInterface* aInterface,
 Lines 1888-1907    Link Here 
1888
    // This is only called while locked (during XPCWrappedNative::FindTearOff).
1943
    // This is only called while locked (during XPCWrappedNative::FindTearOff).
1889
1944
1890
    // Determine if the object really does this interface...
1945
    // Determine if the object really does this interface...
1891
1946
    nsresult rv;
1892
    const nsIID* iid = aInterface->GetIID();
1947
    const nsIID* iid = aInterface->GetIID();
1893
    nsISupports* identity = GetIdentityObject();
1948
    nsISupports* identity = GetIdentityObject();
1894
    nsISupports* obj;
1949
    nsISupports* obj;
1895
1950
1896
    // If the scriptable helper forbids us from reflecting additional
1951
    // Check to see if we should allow this QI
1897
    // interfaces, then don't even try the QI, just fail.
1952
    rv = ShouldAllowQI(identity, aInterface);
1898
    if(mScriptableInfo &&
1953
    if (NS_FAILED(rv)) { return rv; };
1899
       mScriptableInfo->GetFlags().ClassInfoInterfacesOnly() &&
1900
       !mSet->HasInterface(aInterface) &&
1901
       !mSet->HasInterfaceWithAncestor(aInterface))
1902
    {
1903
        return NS_ERROR_NO_INTERFACE;
1904
    }
1905
1954
1906
    // We are about to call out to unlock and other code.
1955
    // We are about to call out to unlock and other code.
1907
    // So protect our intended tearoff.
1956
    // So protect our intended tearoff.
 Lines 2051-2058    Link Here 
2051
    // Note: we do not cache the result of the previous call to HasInterface()
2100
    // Note: we do not cache the result of the previous call to HasInterface()
2052
    // because we unlocked and called out in the interim and the result of the
2101
    // because we unlocked and called out in the interim and the result of the
2053
    // previous call might not be correct anymore.
2102
    // previous call might not be correct anymore.
2054
2103
    if(!mSet->HasInterface(aInterface) &&
2055
    if(!mSet->HasInterface(aInterface) && !ExtendSet(ccx, aInterface))
2104
       !ExtendSet(ccx, aInterface))
2056
    {
2105
    {
2057
        NS_RELEASE(obj);
2106
        NS_RELEASE(obj);
2058
        aTearOff->SetInterface(nsnull);
2107
        aTearOff->SetInterface(nsnull);
 Lines 2061-2066    Link Here 
2061
2110
2062
    aTearOff->SetInterface(aInterface);
2111
    aTearOff->SetInterface(aInterface);
2063
    aTearOff->SetNative(obj);
2112
    aTearOff->SetNative(obj);
2113
    if (rv == NS_SUCCESS_XPC_DONT_CACHE_TEAROFF)
2114
        aInterface->MarkUnsafe();
2115
2064
#ifdef XPC_IDISPATCH_SUPPORT
2116
#ifdef XPC_IDISPATCH_SUPPORT
2065
    // Are we building a tearoff for IDispatch?
2117
    // Are we building a tearoff for IDispatch?
2066
    if(iid->Equals(NSID_IDISPATCH))
2118
    if(iid->Equals(NSID_IDISPATCH))
 Lines 2071-2077    Link Here 
2071
    if(needJSObject && !InitTearOffJSObject(ccx, aTearOff))
2123
    if(needJSObject && !InitTearOffJSObject(ccx, aTearOff))
2072
        return NS_ERROR_OUT_OF_MEMORY;
2124
        return NS_ERROR_OUT_OF_MEMORY;
2073
2125
2074
    return NS_OK;
2126
    return rv;
2075
}
2127
}
2076
2128
2077
JSBool
2129
JSBool
(-)a/js/src/xpconnect/src/xpcwrappednativejsops.cpp (-1 / +7 lines)
Line     Link Here 
 Lines 1173-1181    Link Here 
1173
        XPCNativeMember* member;
1173
        XPCNativeMember* member;
1174
        XPCNativeInterface* iface;
1174
        XPCNativeInterface* iface;
1175
        JSBool IsLocal;
1175
        JSBool IsLocal;
1176
        PRBool isPrivileged;
1176
1177
1177
        if(set->FindMember(id, &member, &iface, protoSet, &IsLocal) &&
1178
        if(set->FindMember(id, &member, &iface, protoSet, &IsLocal) &&
1178
           IsLocal)
1179
           IsLocal && 
1180
           !(iface->IsUnsafe() &&
1181
             (!NS_SUCCEEDED(XPCWrapper::GetSecurityManager()->
1182
                            IsCapabilityEnabled("UniversalXPConnect",
1183
                                                &isPrivileged)) ||
1184
              !isPrivileged)))
1179
        {
1185
        {
1180
            XPCWrappedNative* oldResolvingWrapper;
1186
            XPCWrappedNative* oldResolvingWrapper;
1181
1187

Return to bug 605271