2

C++ Binder API を使用して、特権のない 2 つのプロセス間で通信することはできますか?

私が見つけたすべての例 (例: https://github.com/mcr/Android-HelloWorldServiceServiceManager->addService() )は、ルート化されていない電話で実行すると次のエラーをスローするサービスの登録に依存しています。

E/ServiceManager﹕ add_service('my.test.service',0x48) uid=2000 - PERMISSION DENIED
4

1 に答える 1

2

ファイル Frameworks/native/cmds/servicemanager/service_manager.c の AOSP (Android オープン ソース プロジェクト) 内で、次のメソッドを見つけることができます。

int svc_can_register(uid_t uid, const uint16_t *name)
{
    size_t n;

    if ((uid == 0) || (uid == AID_SYSTEM))
        return 1;

    for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
        if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
            return 1;

    return 0;
}

そして少し上:

/* TODO:
 * These should come from a config file or perhaps be
 * based on some namespace rules of some sort (media
 * uid can register media.*, etc)
 */
static struct {
    uid_t uid;
    const char *name;
} allowed[] = {
    { AID_MEDIA, "media.audio_flinger" },
    { AID_MEDIA, "media.log" },
    { AID_MEDIA, "media.player" },
    { AID_MEDIA, "media.camera" },
    { AID_MEDIA, "media.audio_policy" },
    { AID_DRM,   "drm.drmManager" },
    { AID_NFC,   "nfc" },
    { AID_BLUETOOTH, "bluetooth" },
    { AID_RADIO, "radio.phone" },
    { AID_RADIO, "radio.sms" },
    { AID_RADIO, "radio.phonesubinfo" },
    { AID_RADIO, "radio.simphonebook" },
/* TODO: remove after phone services are updated: */
    { AID_RADIO, "phone" },
    { AID_RADIO, "sip" },
    { AID_RADIO, "isms" },
    { AID_RADIO, "iphonesubinfo" },
    { AID_RADIO, "simphonebook" },
    { AID_MEDIA, "common_time.clock" },
    { AID_MEDIA, "common_time.config" },
    { AID_KEYSTORE, "android.security.keystore" },
};

さらに下:

if (!svc_can_register(uid, s)) {
    ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
         str8(s), handle, uid);
    return -1;
}

結論: /system/bin/servicemanager のシステム バイナリでは許可されていません。(セキュリティ上の理由から) 考えられる解決策:

  • リストされているサービスの PID と名前を削除して再利用する
  • 独自の servicemanager バイナリを再コンパイルして、これを使用します
  • このバイナリにコードを挿入して、誰もが許可できるようにします
  • servicemanager が読み取る PID を変更します (servicemanager が bind.h (同じディレクトリ) で取得する ioctl 応答を変更します)
  • または、ルート権限を持つバイナリでサーバーを起動するだけです。クライアントはルートなしで接続できますが、サーバーはそれを必要とします。
于 2014-09-10T15:09:05.953 に答える