I have an OSX Application that I am working on. It is not sandboxed (it is an internal application that does things which prevent sandboxing).
At some point my application kicks off an auxiliary application, really just a command line application. I would like to be able to strip this application of being able to do anything except write files into the TMPDIR. I am trying to follow the principle of least privilege.
The current code I am using is:
NSTask* task = [NSTask new];
NSBundle* thisBundle = [NSBundle mainBundle];
[task setArguments:#[a, b, c]];
[task setLaunchPath:[thisBundle pathForAuxiliaryExecutable:#"MyProgram"]];
[task launch];
Is this possible with NSTask? If not, what mechanisms can I use to start MyProgram with very low privileges?
The best tool for this is called XPC. It was kind of weak in 10.7, but in 10.8 it's incredibly powerful. Its entire purpose is to let you segment your program this way, while making the IPC very easy. Some docs:
"Creating XPC Services" in Daemons and Services Programming Guide
NSXPCConnection
Cocoa Interprocess Communication With XPC (WWDC 2012 session)
Introducing XPC (WWDC 2011 session)
ObjectToXPC - 3rdparty library. I haven't played with it but it promises to do object marshaling in 10.7 (see below why object marshaling can be dangerous, though). You could also just use your own JSON protocol or the like.
One of the great changes for XPC in 10.8 is that they added NSSecureCoding. They modified the compiler to inject class information into protocol definitions so that object marshaling can be done more safely. This means that when you say that a ObjC protocol passes an NSString, they can actually check that the object is an NSString. (Before 10.8, there was no class information in the Protocol object. You could only check whether an argument should be "an object.")
Who cares? Well, say I hijack your low-privilege task and trick it into returning an NSSomethingElse rather than an NSString (maybe I just overwrite the isa pointer to modify its class). And let's say that NSSomethingElse has a length method that does something useful to me as the attacker. Now, when your high-privilege task calls [returnedValue length], it's going to run the wrong method. Alternately, maybe NSSomethingElse has no length method, so I can force the high-privelege task to throw a "does not implement selector" exception, which could be useful to me as well. With NSSecureCoding, this kind of attack is much harder. It can introspect the returned object, note that it isn't an NSString, and refuse to return it to the calling code.
Even without the niceties of NSXPCConnection, I recommend XPC for this kind of work if you're targeting 10.7+.
Related
What is the best practice for mixing Objective-C ARC with longjmp?
I am using Lua as scripting language, and my platform exports custom library for scripts. Entry points do check arguments with luaL_checkinteger(L, 2) (among others), which, in turn, may call luaL_typerror(L, 2, ...), that is implemented in Lua with setjmp/longjmp. As far as I know, ARC simply auto-generates retain/release code, but what happens if it longjmps out of scope? Will this code leak on mistyped arguments?
static int
set_tag(lua_State *L)
{
NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
[control setTag:(NSInteger)luaL_checkinteger(L, 2)]; // may longjmp!
return 0;
}
In the snippet above, control will be temporarily retained by ARC, but with longjmps uncatchable nature, corresponding release call may never happen. On the other hand, all arguments may be checked before assigning to control variable.
static int
set_tag(lua_State *L)
{
NSInteger tag = luaL_checkinteger(L, 2); // may longjmp!
NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
[control setTag:tag];
return 0;
}
Does it resolve [potential] leak above? Are there better ways to do this?
UPDATE: longjmp only unwinds to Lua internals, and never crosses any system code, except for Lua source (which is aware), and my entry points (which I hope are aware).
I'm pretty sure that second snippet does right, but I need kind of formal proof.
LATE UPDATE:
LuaJIT implements dwarf2-compatible errors, so they are just like C++ exceptions. Pass -fobjc-arc-exceptions compiler flag to arc-enabled sources with Lua code and any retained object will be released on any lua_error. Nothing to worry about now! You are still not allowed to throw errors across Cocoa runtime, though.
I recall that original Lua may be compiled with exceptions too, but I'm not sure.
Doesn't really matter if ARC is in use or not; any setjmp/longjmp that jumps over any frame of code from the system frameworks will yield undefined behavior (for the same reason that exceptions cannot be used for recoverable error handling).
So, yes, that code might leak. Might because it depends on whether the compiler emits a retain/release in that block and where. Might also because whether the compiler emits retain/release will be impacted by the optimization level and, over time, the version of the compiler.
longjmp only unwinds to Lua internals, and never crosses any system
code, except for Lua source (which is aware), and my entry points
(which I hope are aware).
That is helpful. As long as you structure your entry points such that they never intermingle system scope with Lua jumpable scopes, you should be OK. I would recommend turning off ARC in the source files where you have to manage this (and, of course, put the ObjC->Lua interface into a nicely encapsulated bit of implementation so the rest of your code can be ARC clean).
Consider, though, that there is non-obvious risk:
for(id x in anArray) {
... lua call that causes longjmp ...
}
The above would cause lua to "jump over" system code. Same goes for enumerateWithBlock:, KVO, Notification handlers, etc...
You're going to have to think very very carefully about every potential stack trigger by a call from Lua into your code. If that call triggers any kind of automated behavior on the part of the system that could then call Lua API that could trigger a longjmp, all bets are off.
longjmp() may cause crashes or leaks in ARC. Arranging the code so longjmp() and ARC don't interfere is difficult.
If the longjmp() is only for a fatal error path and you expect to halt the process in response then you may be able to ignore the problem. This is what ARC does with C++/ObjC exceptions by default. ARC code is expected to leak when exceptions are thrown. There's a compiler option to enable the clean up code for exceptions, but that hurts performance.
If the longjmp() is not a process-killing error then your best option is to turn off ARC in any code that may be skipped by a longjmp() call.
I found an implementation of a priority queue that primarily uses CFBinaryHeap to work.
I'm currently using the -fno-objc-arc compiler flag to skip the usage of ARC while compiling these files. I attempted to update this code to take advantage of ARC, though I've run into a few snags of understanding.
Is there anyone here who has updated code similar to this for use with ARC?
How do you handle things like free(), and CFRelease()? Can we just get rid of them?
What do you do with the retain and release methods you create for CFBinaryHeapCallBacks?
Do you use __bride or __bridge_transfer to reference the const void * into Objective-C objects? Likewise should you use (__bridge_retained void *) or obj_unretainedPointer() to do the reverse?
ARC basically is a compiler technology that automatically inserts calls to -retain, -release, and -autorelease as needed. It does not remove the need for retains and releases, it just makes them automatic (in the process, optimizing out many that are not required, and playing other tricks to make various common patterns much more efficient than if you did it by hand).
ARC knows nothing about Core Foundation, nor about void* objects, malloc, free, or anything other than ObjC memory management.
This means that as long as you use Core Foundation objects, you should continue to use CFRelease. And if you malloc memory, you should continue to free it.
But.... what if you want to take memory that was created by Core Foundation and transfer it to Cocoa via a toll-free bridge? That's where __bridge* comes in. One of the best sources of information is the clang docs themselves. A great blog article is Everything you need to know about ARC. It includes many useful links to the definitive information.
But here's the short answer (from Transitioning to ARC)
NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
CFStringRef d = (__bridge_retained CFStringRef)my_id; // returned CFRef is +1
Using __bridge_transfer logically moves a CF object into Cocoa. Using __bridge_retained logically moves a Cocoa object into CF. You use these when you are really transferring ownership of the object. In the above example, you generally shouldn't continue using the my_ variables in my opinion. These are particularly useful in cases where you are returning the result out of the function. These should be used for their logical ownership functionality only. Don't use them as a way to "fake" a manual call to retain or release.
If you just want to have a temporary "bridged" pointer to the object so you can use it in CF or Cocoa without transferring it, then use __bridge. That's a no-op that says "don't do any memory management, just let me pretend for the moment that it's the other kind of object." If you do a lot of toll-free bridging, you'll wind up using __bridge quite a lot (making it seem like a small toll.... :D)
Here is a pure objective-c implementation of PriorityQueue, that supports ARC:
https://github.com/jessedc/JCPriorityQueue/tree/experimental/heap-queue
Is simple to implement non ARC lib into XCode project. Just open "Build Phases"(menu when click on your project target) -> "Compile Sources" and to files, which are not using ARC add by double click flag "-fno-objc-arc" and your're done. So simple :)
As I understand it, an unimplemented method gets resolved in the following way:
resolveInstanceMethod: / resolveClassMethod: gets a chance to implement the method
forwardingTargetForSelector: gets a chance to forward to a delegate
forwardInvocation: gets a chance to handle the method as it sees fit.
Where is this three-step process defined? I'd like to handle it myself as NSInvocation might be too heavyweight for my needs. I've had a poke around the runtime source and can't really see anything.
It looks like the old runtime would call forward:args: on the receiver, to do this but that seems to have gone from the new one. I'm guessing that the process must be defined by the framework rather than the runtime, since it'd be strange if the runtime depended on Cocoa to the extent of requiring NSInvocation to handle messages. Is it maybe an undocumented method that gets called on NSObject / NSProxy?
Edit:
It looks like the runtime declares, but never defines, a C function which is called when objc_msgSend can't find an implementation:
id objc_msgForward(id object,SEL message,...);
I don't work for Apple, so I don't know how Foundation implements this, but at least in the case of Cocotron, they use:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,#selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,#selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
adding a forwardSelector:arguments: method doesn't seem to work, so I'm guessing this is specific to Cocotron. Anyone know what objc_msgForward does in Foundation?
I'm writing something a bit like a
scripting language that uses message
forwarding to interface with
objective-c. For now, I'm using
NSInvocation, but it could end up
doing this thousands of times per
second, so the overhead would be
noticeable. But I guess I'm also just
curious...
As far as message forwarding is concerned, the behavior is [often subtly] different across different platforms and versions of the runtime.
In any case, don't re-invent the wheel. There are two language bridges available today that do pretty close to full-fidelity bridging from which you can learn a ton. Both have liberal licenses specifically to allow for such re-use.
Specifically, the MacRuby project offers a Ruby implementation that sits on top of CoreFoundation and the Objective-C Garbage Collector. It is the "most native" bridge available (and not terribly portable as a result -- not a goal of the project).
The PyObjC bridge is the best example available of a high fidelity bridge between the Objective-C runtime and another dynamic OO language's runtime; Python. It is a bit more portable, though the non-Mac OS X bits have likely rotted somewhat.
(I would be remiss in not mentioning F-Script; a new language built on Objective-C for which, I believe, the source is/was available?)
All of the bridges deal with both method forwarding, subclassing and cross-runtime proxying, all of which sound like they are applicable to your particular needs.
so I'm working on my little Mac app, and I want control Adium with it. AppleScript is very cool:
tell application "Adium"
go away with message "Zoned in for Maths."
end tell
(If you're wondering what this is supposed to be. In order to actually start studying I need to create application that will change my IM status, of course ... )
I tried it in Script Editor, it worked, and I'm pretty sure that calling AppleScript from Cocoa application is gonna be trivial.
But.
Is AppleScript the only way? I don't mind using AppleScript, but it looks like programming for noobs.
Is there any way to do the same thing as above code does without AppleScript, in plain Objective-C somehow?
Would someone point me to relevant documentation? I tried Google but it was like I don't even know what I'm looking for.
Thanks!
Interprocess communication in Mac OS X is done by something called Apple Events. AppleScript is one way to send and receive Apple Events to other applications.
Therefore, you just need to construct Apple Events directly and send it to the other app, from Objective-C or whatever other language.
Honestly, if you just want to change the status of Adium, it's easiest to use NSAppleScript and pass what you just wrote, from inside Objective-C.
If you want to do more complicated stuff, Scripting Bridge is the way to go. This mechanism maps Apple Events' object hierarchy to Objective-C's object hierarchy.
If you think that's still a newbie's way, you should directly create Apple Events via NSAppleEventDescriptor.
Well, some of us old timers think using Objective-C is a sissy's way. If you think so, you should directly deal with C structs called AEDesc and such. See Apple Events programming guide and the corresponding reference.
However, I think people who use OS X are all noobs. Real people use Linux.
My dad would say people who use GUI are just too spoiled.
The point is, you don't have to care whether it is a newbie's way or not. The important thing is whether you can achieve what you want. In fact, AppleScript is a very powerful, dynamical language, whose power is not well appreciated by many people. Read AppleScript language guide and be surprised.
The simplest way would be to use NSAppleScript
NSAppleScript *script = [[NSAppleScript alloc]
initWithSource:#"tell application \"Adium\" to go away with message \"Zoned in for Maths.\""
];
For a more powerful way of accessing scripting, use Scripting Bridge. Scripting Bridge requires at least the 10.5 SDK. You first need to prepare your app.
Use the sdef and sdp command line utilities to generating header files for the applications you wish to control (see "Preparing to Code" for details).
Add the generated header to your project.
Add the ScriptingBridge framework to your project. After that, you can use Objective-C calls to control the other application.
After that, you can use Objective-C to send scripting commands to the application.
AdiumApplication *adium = [SBApplication applicationWithBundleIdentifier:#"com.adiumX.adiumX"];
for (AdiumAccount* acct in [adium accounts]) {
[acct goAwayWithMessage:(AdiumRichText *)#"Zoned in for Maths."];
}
Status messages are Adium's rich text type (which is NSTextStorage under the hood), but it's convertable from plain text, so passing an NSString rather than a true AdiumRichText should work fine.
There are a few hoops to jump through. For example, you can't create scripting objects in the target application by using its ObjC classes directly; you must use classForScriptingClass: to get the class, which you can then use to create objects as normal (i.e. alloc and init, initWithProperties &c.).
// creating an AdiumContactGroup
NSDictionary *props = [NSDictionary
dictionaryWithObjectsAndKeys:
#"mathies",#"name",
nil
];
AdiumContactGroup *mathies= [[[[adium classForScriptingClass:#"contact group"] alloc]
initWithProperties:props]
autorelease];
if (mathies) {
[[adium contactGroups] addObject:mathies];
}
Note that other languages (such as Python and Ruby) also have Scripting bindings.
Others have mentioned sending full Applescript or using the Scripting Bridge. A third choice is to use Appscript which is also available for Python and Ruby. It is a little cleaner (IMO) than using the Scripting Bridge in some ways. And definitely easier. Although in other ways Scripting Bridge is better. It also has the advantage of an application called ASTranslate which will translate most Applescript calls into Appscript. Here's the Appscript for your little Applescript example.
ADApplication *adium = [ADApplication applicationWithName: #"Adium"];
ADGoAwayCommand *cmd = [[adium goAway] withMessage: #"Zoned in for Maths."];
id result = [cmd send];
Sorry for long description, however the questions aren't so easy...
My project written without GC. Recently I found a memory leak that I can't find. I did use new Xcode Analyzer without a result. I did read my code line by line and verified all alloc/release/copy/autorelease/mutableCopy/retain and pools... - still nothing.
Preamble: Standard Instruments and Omni Leak Checker don't work for me by some reason (Omin Tool rejects my app, Instruments.app (Leaks) eats too many memory and CPU so I have no chance to use it).
So I wanna write and use my own code to hook & track "all" alloc/allocWithZone:/dealloc messages statistics to write some simple own leaks checking library (the main goal is only to mark objects' class names with possible leaks).
The main hooking technique that I use:
Method originalAllocWithZone = class_getClassMethod([NSObject class],#selector(allocWithZone:));
if (originalAllocWithZone)
{
imp_azo = (t_impAZOriginal)method_getImplementation(originalAllocWithZone);
if (imp_azo)
{
Method hookedAllocWithZone = class_getClassMethod([NSObject class],#selector(hookedAllocWithZone:));
if (hookedAllocWithZone)
{
method_setImplementation(originalAllocWithZone,method_getImplementation(hookedAllocWithZone));
fprintf(stderr,"Leaks Hook: allocWithZone: ; Installed\n");
}
}
}
code like this for hook the alloc method, and dealloc as NSObject category method.
I save IMP for previous methods implementation then register & calculate all alloc/allocWithZone: calls as increment (+1) stat-array NSInteger values, and dealloc calls as decrement (-1).
As end point I call previous implementation and return value.
In concept all works just fine.
If it needs, I can even detect when class are part of class cluster (like NSString, NSPathStore2; NSDate, __NSCFDate)... via some normalize-function (but it doesn't matter for the issues described bellow).
However this technique has some issues:
Not all classes can be caught, for
example, [NSDate date] doesn't catch
in alloc/allocWithZone: at all, however, I can see alloc call in GDB
Since I'm trying to use auto singleton detection technique (based on retainCount readind) to auto exclude some objects from final statistics, NSLocale creation freezes on pre-init stage when starting of full Cocoa application (actually, even simple Objective-C command line utility with the Foundation framework included has some additional initialization before main()) - by GDB there is allocWithZone: calls one after other,....
Full Concept-Project draft sources uploaded here: http://unclemif.com/external/DILeak.zip (3.5 Kb)
Run make from Terminal.app to compile it, run ./concept to show it in action.
The 1st Question: Why I can't catch all object allocations by hooking alloc & allocWithZone: methods?
The 2nd Question: Why hooked allocWithZone: freezes in CFGetRetainCount (or [inst retainCount]) for some classes...
Holy re-inventing the wheel, batman!
You are making this way harder than it needs to be. There is absolutely no need whatsoever to roll your own object tracking tools (though it is an interesting mental exercise).
Because you are using GC, the tools for tracking allocations and identifying leaks are all very mature.
Under GC, a leak will take one of two forms; either there will be a strong reference to the object that should long ago been destroyed or the object has been CFRetain'd without a balancing CFRelease.
The collector is quite adept at figuring out why any given object is remaining beyond its welcome.
Thus, you need to find some set of objects that are sticking around too long. Any object will do. Once you have the address of said object, you can use the Object Graph instrument in Instruments to figure out why it is sticking around; figure out what is still referring to it or where it was retained.
Or, from gdb, use info gc-roots 0xaddr to find all of the various things that are rooting the object. If you turn on malloc history (see the malloc man page), you can get the allocation histories of the objects that are holding the reference.
Oh, without GC, huh...
You are still left with a plethora of tools and no need to re-invent the wheel.
The leaks command line tool will often give you some good clues. Turn on MallocStackLoggingNoCompact to be able to use malloc_history (another command line tool).
Or use the ObjectAlloc instrument.
In any case, you need to identify an object or two that is being leaked. With that, you can figure out what is hanging on to it. In non-GC, that is entirely a case of figuring out why it there is a retain not balanced by a release.
Even without the Leaks instrument, Instruments can still help you.
Start with the Leaks template, then delete the Leaks instrument from it (since you say it uses too much memory). ObjectAlloc alone will tell you all of your objects' allocations and deallocations, and (with an option turned on, which it is by default in the Leaks template) all of their retentions and releases as well.
You can set the ObjectAlloc instrument to only show you objects that still exist; if you bring the application to the point where no objects (or no objects of a certain class) should exist, and such objects do still exist, then you have a leak. You can then drill down to find the cause of the leak.
This video may help.
Start from the Xcode templates. Don't try to roll your own main() routine for a cocoa app until you know what you're doing.