AndroidでWindowsボールをマウントするためのサポートを追加する

最近、私は自分でSamsung Galaxy Tab Pro 10.1 LTE SM-T525タブレットを購入し、自宅のsambaで共有されているネットワークドライブから映画やその他のファイルを見たいと思っていました。 これを行うには、カーネルがCIFSをサポートしている必要があります。また、バージョン4.2以降のアンドロイドでは、これは重要なタスクであることが判明しました。



1.カスタムマウントの問題の本質



実際、バージョン4.2以降、Adnroidはマルチユーザーモードを導入し、すべてのファイルシステムがスレーブとしてマウントされるようになったため、1人のユーザーがマウントしたファイルシステムが他のユーザーから見えなくなります。

バージョン4.2以降のAndroid Dalvik仮想マシンでは、次のコードがvm / Init.cppファイルにあります。

if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) { SLOGE("Failed to mount() rootfs as MS_SLAVE: %s", strerror(errno)); return -1; }
      
      







このコードは、MS_SLAVEおよびMS_RECフラグを使用してルートファイルシステムをマウントします。つまり、/内にマウントされたファイルシステムもデフォルトでMS_SLAVEフラグを使用してマウントされ、それらをマウントしたユーザーとその子プロセスのみがアクセスできます。 この問題を解決するために、do_mount関数のカーネル用の次のパッチがxda-developersを使用してmkasickユーザーによって提案されました。

 --- kernel_orig/fs/namespace.c 2014-01-23 15:34:18.000000000 +1100 +++ kernel/fs/namespace.c 2014-04-11 15:18:22.258114000 +1100 @@ -2141,6 +2141,21 @@ if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; +#ifdef CONFIG_RESTRICT_ROOTFS_SLAVE + /* Check if this is an attempt to mark "/" as recursive-slave. */ + if (strcmp(dir_name, "/") == 0 && flags == (MS_SLAVE | MS_REC)) { + static const char storage[] = "/storage"; + long res; + /* Mark /storage as recursive-slave instead. */ + if ((res = do_mount(NULL, (char *)storage, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) { + return 0; + } else { + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", storage, res); + } + /* Fallback: Mark rootfs as recursive-slave as requested. */ + } +#endif + /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); if (retval)
      
      





パッチの本質は、MS_SVALEおよびMS_RECフラグを使用して/のdo_mount呼び出しをインターセプトし、それらを設定させないことです。 しかし、Androidが機能するには、これらのフラグが/ストレージ内のカスタムファイルシステムに必要です。そうしないと、システムが起動しません。 したがって、do_mount(NULL、(char *)storage、NULL、(MS_SLAVE | MS_REC)、NULL))== 0)を呼び出します。 最後の呼び出しが機能するには、/ storageがディレクトリだけでなくマウントポイントである必要があるため、/ storageディレクトリが作成されるramdiskのinit.rcファイルで、tmpfsをマウントする必要があります。

 mkdir /storage 0050 root sdcard_r mount tmpfs tmpfs /storage mode=0050,uid=0,gid=1028
      
      





これらの操作の後、/ストレージの外部のマウントポイントはすべてのユーザーに表示されます。



2.カーネルアセンブリ



まず、LinuxカーネルにCIFSサポートを追加する必要があります。 これを行うには2つの方法があります。cifsカーネル用のモジュールをコンパイルするか、cifsサポートをカーネル自体に追加します。 最初の方法の方が良い、なぜなら 新しいカーネルをフラッシュして一部のデバイスの保証を失う必要はありません。

タブレットのコアはモジュールのサポートなしで組み立てられることが判明したため、新しいカーネルを再構築してフラッシュする必要がありました。

カーネルを構築するには、次のものが必要です。

a)Linuxマシン

b)デバイスのカーネルソース。Samsungの場合はopensource.samsung.comを取得します

c)アセンブリ用のツールチェーン、 developer.android.com / tools / sdk / ndk / index.htmlをご覧ください

カーネルを構築するには、〜/ androidディレクトリを作成し、その中のカーネルソースをandroid-ndk-r9のandroid-ndkディレクトリに展開します

 mkdir ~/android cd ~/android tar xjf android-ndk-r9d-linux-x86_64.tar.bz2 unzip SM-T525_SEA_KK_Opensource.zip mkdir kernel cd kernel tar xzf ../Kernel.tar.gz
      
      





ここでパッチを適用して、空のマウントポイントの問題を修正します

shared_rootfs.patch
 --- kernel_orig/fs/namespace.c 2014-01-23 15:34:18.000000000 +1100 +++ kernel/fs/namespace.c 2014-04-11 15:18:22.258114000 +1100 @@ -2141,6 +2141,21 @@ if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; +#ifdef CONFIG_RESTRICT_ROOTFS_SLAVE + /* Check if this is an attempt to mark "/" as recursive-slave. */ + if (strcmp(dir_name, "/") == 0 && flags == (MS_SLAVE | MS_REC)) { + static const char storage[] = "/storage"; + long res; + /* Mark /storage as recursive-slave instead. */ + if ((res = do_mount(NULL, (char *)storage, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) { + return 0; + } else { + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", storage, res); + } + /* Fallback: Mark rootfs as recursive-slave as requested. */ + } +#endif + /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); if (retval) --- kernel_orig/fs/Kconfig 2014-01-23 15:34:17.000000000 +1100 +++ kernel/fs/Kconfig 2014-04-10 19:29:30.990114000 +1100 @@ -292,4 +292,29 @@ source "fs/nls/Kconfig" source "fs/dlm/Kconfig" +config RESTRICT_ROOTFS_SLAVE + bool "Android: Restrict rootfs slave mountspace to /storage" + help + Restrict slave mountspace so Dalvik apps can mount system-wide volumes + + Android 4.2 implements multi-user storage using per-process mount + namespaces. Everything under "/" (the entire filesystem hierarchy) is + marked as a recursive-slave mountspace for all zygote instances. This is + done so that user-storage sandbox mounts under /storage/emulated are hidden + from other apps and users. Unfortunately this means that any Dalvik app + (actually, any program whose clone/fork ancestry includes a Dalvik zygote, + which is everything except services spawned directly from init) cannot + mount system-wide volumes. + + This option restricts rootfs-slave calls to /storage (and + /mnt/shell/emulated) so that Dalvik apps can mount system-wide volumes + elsewhere (with appropriate permission, as in earlier versions of Android), + while retaining full multi-user storage compatibility. It is made + available as a kernel-based workaround for instances where libdvm can not + be modified. + + This option requires that a tmpfs volume is mounted as /storage in + Android init.rc. If this volume is unavailable, then we fall back to the + previous behavior of marking the entire filesystem hierarchy as slave. + endmenu
      
      







 patch -p1 < shared_rootfs.patch
      
      





次に、環境変数を登録してカーネル構成ファイルを準備する必要があります。Samsungの場合は次のようになります。

 export CROSS_COMPILE="~/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-" export ARCH="arm" make mrproper make VARIANT_DEFCONFIG=msm8974_sec_picassoeur_defconfig msm8974_sec_defconfig SELINUX_DEFCONFIG=selinux_defconfig
      
      





このコマンドは.configファイルを作成します。その後、 make menuconfigコマンドを実行し、[ファイルシステム]-> [ネットワークファイルシステム]セクションに移動し、CIFSサポート項目を確認する必要があります(モジュールが構築されている場合、文字Mでマークします)。ファイルシステムセクションでRESTRICT_ROOTFS_SLAVEをマークします



次に、Escで終了し、構成を保存します。 ここで、コマンドmake -j3を使用してカーネルをアセンブルします(数値3の代わりに、プロセッサコアの数+ 1を示します)。

これでカーネルアセンブリが完了します。



3.ファームウェア用のboot.imgをビルドします



次に、新しいカーネルをタブレットにフラッシュする必要があります。 これを行うには、カーネル、ramdisk、およびQualcommチップのデバイスツリーを含むboot.imgイメージを構築する必要があります。

最初に、ネイティブRAMディスクを取得する必要があります。これには、元のファームウェア(これは通常のtar)を解凍し、そこからboot.imgファイルを取得します

 tar xf T525XXUANB2_T525SERANA6_T525XXUANA7_HOME.tar.md5 boot.img
      
      





boot.imgを展開するには、 bootimg_toolsパッケージが必要です。

〜/ androidにダウンロードし、split_bootコマンドでboot.imgファイルを解凍します。

 mkdir ~/adndroid/bootimg_tools cd ~/adnroid/bootimg_tools unzip ../bootimg_tools_7.8.13.zip ./split_boot ../boot.img
      
      





そして、boot / ramdiskディレクトリに解凍されたramdiskを取得します

次に、ramdisk内のいくつかのファイルを修正して、Selinuxを許容モードに変換し、tmpfsとしてマウント/ストレージする必要があります。

init.rcファイルで、 setsebool debugfs 1という行を探し、次の行に置き換えます。

 setsebool debugfs 0 setenforce 0
      
      





次に、行setprop selinux.reload_policy 1を探して、 setprop selinux.reload_policy 0に変更します。

tmpfsとして/ storageをマウントするには、 mkdir / storage 0751 root sdcard_rの行を探して、その後に追加します

 mount tmpfs tmpfs /storage mode=0050,uid=0,gid=1028
      
      





また、defaul.propファイルで、 ro.secure = 1ro.secure = 0に変更し、 ro.adb.secure = 1ro.adb.secure = 0に変更します



ラムディスクを回収します

 ./repack_ramdisk boot/ramdisk ramdisk.cpio.gz cp boot/ramdisk.cpio.gz ~/android/kernel
      
      





さらに、アセンブリには、まだdt.imgファイルが必要です。このファイルは、カーネルに付属しているdtbToolユーティリティによって生成されます

 cd ~/android/kernel ./tools/dtbTool -o dt.img -s 2048 -p ./scripts/dtc/ ./arch/arm/boot/
      
      





boot.imgをビルドするために必要なものがすべて揃ったので、mkbootimgユーティリティを使用してアセンブリ自体を開始します(カーネルにも付属しています)。

 ./tools/mkbootimg --kernel ./arch/arm/boot/zImage --ramdisk ramdisk.cpio.gz --cmdline 'console=null androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3' --base 0x00000000 --pagesize 2048 --ramdisk_offset 0x02000000 --tags_offset 0x01E00000 --dt dt.img -o boot.img
      
      





すべて、boot.imgファイルの準備ができました。 Odinを介してフラッシュするには、そこからboot.tar.md5を作成します

 tar -H ustar -c boot.img > boot.tar md5sum -t boot.tar >> boot.tar mv boot.tar boot.tar.md5
      
      





今オーディンを介してそれをフラッシュ





Samsungでは、wifiがkatomカーネルでの動作を停止するという問題があります。これは、動作中のシステムでbuild.propファイルを編集することで処理されます。 行ro.securestorage.support = truero.securestorage.support = falseに置き換える必要があります



4.マウント用のソフトウェアのセットアップ



ボールをマウントするには、 CifsManagerプログラムを使用します







セットアップにはいくつかのニュアンスがあります。

a)3.4カーネルのcifsで何かが壊れていましたが、現在はmountコマンドのデバイスパラメーターを処理しません。 デザインを見る

mount -t cifs //pc/share /mnt



なくなりました。マウントされたボールはuncパラメーターで指定する必要があります。 前のコマンドは次のようになります。

 mount -t cifs -o unc=\\\\pc\\share none /mnt
      
      





b)マウントポイントについて。 上記のように、/ストレージの内部にマウントすると、そのようなボールは他のアプリケーションでは空になります./ストレージの外部のどこかにマウントすると、ほとんどのアプリケーションはそれを開くことができません メモリカード内でのみファイルを開くことができます。 抜け道があります。 内部メモリ/ストレージ/エミュレート/ 0は実際には/データ/メディア/ 0にあり、/ストレージ/エミュレート/ 0はこのディレクトリのfat32エミュレーションです。 したがって、たとえば/ data / media / 0 / cifsに安全にマウントし、内部ストレージのファイルマネージャーでボールを確認できます。

c)まだ説明されていないニュアンスがあります;何らかの理由でmount -t cifsコマンドは、たとえばコマンド内のパスワードの後に​​来るパラメーターを無視します

 mount -t cifs -o unc=\\\\pc\\share,username=user,password=123,sec=ntlmssp none /data/media/0/cifs
      
      





sec = ntlmsspパラメーターは処理されません。 したがって、ボールに接続するためにパスワードが必要な場合は、CifsManagerで[パスワード]フィールドを空のままにし、上記のスクリーンショットのように最後の[オプション]フィールドにパスワードを書き込みます。

d)ファイル名にロシア語の文字を正しく使用するには、オプションiocharset = utf8を追加する必要があります



CifsManagerでボールをマウントしてお楽しみください!



次のソースの資料を使用しました。

www.ibm.com/developerworks/en/library/l-mount-namespaces

forum.xda-developers.com/showthread.php?p=36889027

www.netzgewitter.com/2013/10/troubleshoot-cifs-on-android



All Articles