我们用SMJobBless更新辅助工具时遇到了一个问题,这种问题困扰了我们好几天了。

我们正在开发一个应用程序,在某些时候我们需要针对该应用程序执行管理任务(加载/卸载kext)。我们还使用钥匙串(keychain)存储应用程序的帐户信息。

对于管理任务,我们使用通过SMJobBless安装的帮助程序工具,通过Mach端口(通过NSConnection)与DO进行通信,该工具与one other post一起使用。

在辅助工具中:

// use our bundle id as our service name
NSString* name = [[NSBundle mainBundle] bundleIdentifier];

launch_data_t checkinRequest = launch_data_new_string(LAUNCH_KEY_CHECKIN);
launch_data_t checkinResponse = launch_msg(checkinRequest);
launch_data_t machServicesDict = launch_data_dict_lookup(checkinResponse, LAUNCH_JOBKEY_MACHSERVICES);
launch_data_t machPort = launch_data_dict_lookup(machServicesDict, [name UTF8String]);

mach_port_t mp = launch_data_get_machport(machPort);

launch_data_free(checkinResponse);
launch_data_free(checkinRequest);

NSMachPort *receivePort = [[NSMachPort alloc] initWithMachPort:mp];
NSConnection *server = [NSConnection connectionWithReceivePort:receivePort sendPort:nil];

在应用程序中:
NSConnection *conn = [NSConnection connectionWithRegisteredName:HELPER_BUNDLE_IDENTIFIER host:nil];

id proxyServerObject = [conn rootProxy];

if(conn && proxyServerObject) {
    return [proxyServerObject someMethod];
}
return NO;

我们使用Thawte的代码签名证书对应用程序和帮助程序工具进行签名。到目前为止,一切都像魅力一样。帮助工具已安装,我们可以使用DO与它进行通信;我们的kext已成功加载和卸载。

当我们尝试更新我们的助手工具时,问题就开始了。我们使用应用程序 bundle 包中已安装工具和 bundle 工具的信息字典来检查是否需要更新工具,然后再次调用SMJobBless来执行更新。

调用SMJobBless之后,控制台中将出现以下几行:
6/19/12 10:31:24.000 AM kernel: CODE SIGNING: cs_invalid_page(0x104e17000): p=74362[OURAPP] clearing CS_VALID
6/19/12 10:31:24.000 AM kernel: CODE SIGNING: cs_invalid_page(0x10d0de000): p=74364[OURAPPHELPER] clearing CS_VALID

此后,应用程序无法从我们的钥匙串(keychain)项中读取应用程序密码,函数SecKeychainItemCopyContent返回errSecAuthFailed (-25293)。但是,如果我们使用codesign -vvvv PATH_TO_TOOL_OR_BUNDLE手动验证已安装的帮助程序工具或应用程序 bundle 包的代码签名,则不会报告任何错误。
该工具和应用程序是在Xcode环境外部签名的,并且在签名过程之后,其内容不会更改。

我们发现SMJobBless returning error 4098描述了类似的情况,但该问题仍未得到解答。
一个相关的问题可能是ojit_a。

我们正在OSX 10.7.4上进行测试。

任何人都面临类似的问题,或者我们做错了什么明显的事情吗?

最佳答案

这是由于与SMJobBless替换磁盘上的辅助工具有关的错误所致。特别是,它修改了二进制文件的位置,而不是采用写入临时文件然后在目标顶部重命名的通用方法。这样的效果是,如果二进制文件位于内存中,则对该文件的修改将更改支持该文件的内存页,从而使它们的代码签名无效。我已将有关此问题的错误报告写为rdar:// problem / 13514523。如果您尚未提交,我建议您自己提交。

可能的解决方法是让您的应用程序在使用SMJobBless升级之前,先请求帮助程序工具将其自身从磁盘中删除。这应该导致SMJobBless复制到磁盘上的新文件,从而绕过该问题。

10-01 09:48