1. 程式人生 > >xxx.so has text relocations. This is wasting memory and is a security risk. Please fix

xxx.so has text relocations. This is wasting memory and is a security risk. Please fix

 最近使用jni編譯so檔案,發現在Android M中將之前一直視為warning的text relocation升級為了error ,直接導致system.load so檔案的時候失敗。翻了網上各種資料,關於text relocation的解決辦法總結了一下:

這個錯誤的主要原因是載入.so檔案的程式碼段時,程式碼段引用的資料物件需要重定位, 重定位會修改程式碼段的內容,這就造成每個使用這個.so檔案程式碼段的程序在核心裡都會生成這個.so檔案程式碼段的copy.每個copy都不一樣,取決於 這個.so檔案程式碼段和資料段記憶體對映的位置.

1、遇到該問題,首先檢查ndk版本,如果版本為r8c一下,請首先升級ndk版本到最新

2、仍然不能解決,You need to make the code in your library position independent...add -fpic or -fPIC to your LOCALC_FLAGS in your Android.mk and you also need to ensure that you're not linking against any static or shared libraries that contain text relocations themselves. If they do and you can re-compile them, use one of the flags mentioned above.

-fpic為gcc使用方法,主要是生成與地址無關的可執行檔案。具體解釋見連結:

為防止唄牆,這裡保留一份:

Text Relocations

When code is executed by a processor it must usually access various parts of the address space to access objects like variables or functions. There are two ways in which objects can be access:

  • with their absolute address in the address space
  • with relative addresses, i.e., the difference between two addresses

The former seem to be the most obvious choice. At runtime each object has a fixed address which has to be known and can be used. There are two key words in this sentence: at runtime. The final layout of the address space is often not fixed until runtime. In the early days this was no problem. Programs consisted of one big block of code loaded at a fixed address. But today we have shared libraries and position independent executables (PIEs). For those kinds of position independent binaries the actual address used at runtime is not known until the binary is loaded. Referencing any object in an position independent binary cannot simply happen with an absolute address. There are two solutions of different efficiency for two different situations:

  1. The references to an object from a function in the same position independent binary can take advantage of the fact that regardless of where the binary is loaded, the relative distance between a specific point in the binary and the object is constant. Using addressing relative to a fixed point in the binary means that once the address of the fixed point in the object is determine all that is needed is to add the offset to the value to get the final address. The generated code does not need any change as long as the base value is treated as a variable.Some processors allow even simpler handling of this: the address of the instruction can be implicitly used as the base value. This requires no base value kept around.

  2. For references from a function in one binary to an object in another binary there is no fixed offset which can be determined at link-time. With ELF the final object might not even be found in the same binary for every start of the program. Therefore it is necessary to dynamically compute the address of the object the first time it is used in each program run.

How to generate programs to create the best possible references and many more things about position independent binaries is explained in my DSO How-To. What is explained in the following sections is how to correct the mistake of not using the correct way to generate position independent binaries. The result of such mistakes are text relocations. Some of the more modern architectures architecture (or more correctly, their ABIs) actively forbid text relocations. But there are others and unfortunately x86 is among them.

What do they look like?

A text relocation is the result of a reference to an object with a variable address at runtime using an absolute addressing mode. The instruction encoding itself contains the address and therefore the executable text of the binary must be changed to contain the correct address when taking the actual load addresses at runtime into account.

The result of a text relocation is that the binary text is written to. This means this page of the binary cannot be physically shared with other processes on the system (this is the goal of DSOs, aka shared libraries). It also means that the binary must have permission to change the access permissions for the memory page to include writing and then back to executing. This is a privileged operation when SELinux is enabled. I have a write-up of the ways this privilege mechanism makes itself known and how it can be controlled, if necessary.

Spotting binaries with text relocations is simple. The linker is supposed to mark them. It sets the DF_TEXTREL bit in the DT_FLAGS entry in the dynamic section. In older binaries a DT_TEXTREL entry is present. In any case, a binary with text relocations can be spotted with this:

eu-readelf -d  | fgrep -q TEXTREL

If this command pipeline exits with a zero status a text relocation is present.

This is the easy part of recognizing text relocations. It is more difficult to spot the exact relocation record(s) responsible for the TEXTREL flag. The relocation records of a binary can be viewed with

eu-readelf -r 

The first column is the address. Every address that is in the range of a segment which is loaded without write permission indicates a text relocation. The addresses of the segments can be seen with

eu-readelf -l  | fgrep LOAD

This alone can be pretty time consuming but it gets worse.

What is responsible?

To be able to remove the text relocation it is necessary to find out what piece of code corresponds to the address with the text relocation. The minimum information needed is a function name. Better yet is it to get the source file name and line number information as well. To get all this one can look through the symbol tables and debug information of the binary. eu-readelf provides all this information as well.but it is tedious to get to it. There is the eu-addr2lineprogram which can make this much simpler. Given a binary name, the program can provide source file and line information for all the address given as input.

This is still quite complicated. It means three steps to arrive at the result. Too much for most developers who are not accustomed with binary formats or cannot find the time to dig into the details.

There is Help

Because text relocations are a huge problem and because it is obvious that programmers are not willing to put in the time to figure out the details I have written a tool which automates the process. It is, just like the other programs mentioned here, part of the elfutils package. Before we see how to use the program look at this code:

int a;
int
main (void)
{
  return a;
}

If this code is compiled on x86 with

gcc -o u -g -pie u.c

one can verify with the above mentioned commands that the resulting binary contains text relocations. The explained three steps can be used to find the reason for the text relocation. Or: one can run a single command:

eu-findtextrel u

In the case of this binaries the result of this program run will be the following output:

/home/drepper/local/elfutils-build/20060530/u.c not compiled with -fpic/-fPIC

That's as precise as one gets it. The solution is indeed to pass additional parameters to the compiler. -fpic and -fPIC are mentioned here (see the DSO How-To for the difference). The tool could also have mentioned -fpie and -fPIE which might be more optimal in this case. In any case, the solution for most C files is as simple as this.

The tool is not able to distinguish compiler-generated code from assembler code written by the programmer. In both cases the tool will print the message above since it is what is correct in 99% of all cases. If the problem is indeed the result of hand-written assembler code the solution is not as simple as adding a compiler/assembler flag. The code needs to be rewritten. This is architecture specific and can vary widely between every single instance. We are not going into those details here. Find a person with sufficient assembly programming skills if this problem appears.

The program above was compiled with debugging enabled. If this is not the case or the debug information is not available the tool cannot give information about the file which must be recompiled. In this case the output looks like this:

the file containing the function 'main' is not compiled with -fpic/-fPIC

It is left to the person who has to fix the problem to map the function name to a source file. In some situation it is not clear which function is responsible and then the tool gives the user the names of two functions, both of which are candidates. This is still a good situation. Sometimes no information at all is available and then the tool can only provide an address value and it is up to the user to figure out from what sources the code at that address has been generated. The tool does all it can to give as good information as possible. But there are limits. To not be exposed to the limits it is best to have debug information available.

Conclusion

Using the eu-findtextrel program it is in most situations relatively painless to determine the culprit(s) for the text relocations easily. There is usually no reason to not fix the problems. While a programs with text relocations can be made to run by relaxing the SELinux security this is a bad idea. The kind of permissions which have to be granted to the program create a gaping hole in the security policy. Attackers will be able to modify the memory as well. If this is not the case a program can enforce a strict W^X policy. I.e., no memory page is writable and executable at the same time. And more: SElinux can also enforce that no writable page can be marked as read/exec-only. With these provisions an attacker has no room where to place his/her exploit code. This is a huge win. So, always fix all text relocations. We've made it as easy as possible.

3、如果在so中,動態連結了其他可執行檔案,比如.o檔案,同樣必須要保證.o檔案使用-fpic編譯,不能有text relocation問題

-fPIC 作用於編譯階段,告訴編譯器產生與位置無關程式碼(Position-Independent Code),
則產生的程式碼中,沒有絕對地址,全部使用相對地址,故而程式碼可以被載入器載入到記憶體的任意
  位置,都可以正確的執行。這正是共享庫所要求的,共享庫被載入時,在記憶體的位置不是固定的。

gcc -shared -fPIC -o 1.so 1.c 這裡有一個-fPIC引數 PIC就是position independent code PIC使.so檔案的程式碼段變為真正意義上的共享 如果不加-fPIC,則載入.so檔案的程式碼段時,程式碼段引用的資料物件需要重定位, 重定位會修改程式碼段的內容,這就造成每個使用這個.so檔案程式碼段的程序在核心裡都會生成這個.so檔案程式碼段的copy.每個copy都不一樣,取決於 這個.so檔案程式碼段和資料段記憶體對映的位置.

不加fPIC編譯出來的so,是要再載入時根據載入到的位置再次重定位的.(因為它裡面的程式碼並不是位置無關程式碼)
如果被多個應用程式共同使用,那麼它們必須每個程式維護一份so的程式碼副本了.(因為so被每個程式載入的位置都不同,顯然這些重定位後的程式碼也不同,當然不能共享)
我們總是用fPIC來生成so,也從來不用fPIC來生成a.
fPIC與動態連結可以說基本沒有關係,libc.so一樣可以不用fPIC編譯,只是這樣的so必須要在載入到使用者程式的地址空間時重定向所有表目.

因此,不用fPIC編譯so並不總是不好.
如果你滿足以下4個需求/條件:
1.該庫可能需要經常更新
2.該庫需要非常高的效率(尤其是有很多全域性量的使用時)
3.該庫並不很大.
4.該庫基本不需要被多個應用程式共享

如果用沒有加這個引數的編譯後的共享庫,也可以使用的話,可能是兩個原因:
1:gcc預設開啟-fPIC選項
2:loader使你的程式碼位置無關

從GCC來看,shared應該是包含fPIC選項的,但似乎不是所以系統都支援,所以最好顯式加上fPIC選項。參見如下


`-shared'
     Produce a shared object which can then be linked with other
     objects to form an executable.  Not all systems support this
     option.  For predictable results, you must also specify the same
     set of options that were used to generate code (`-fpic', `-fPIC',
     or model suboptions) when you specify this option.(1)



-fPIC 的使用,會生成 PIC 程式碼,.so 要求為 PIC,以達到動態連結的目的,否則,無法實現動態連結。

non-PIC 與 PIC 程式碼的區別主要在於 access global data, jump label 的不同。
比如一條 access global data 的指令,
non-PIC 的形勢是:ld r3, var1
PIC 的形式則是:ld r3,[email protected],意思是從 GOT 表的 index 為 var1-offset 的地方處
指示的地址處裝載一個值,即[email protected]處的4個 byte 其實就是 var1 的地址。這個地址只有在執行的時候才知道,是由 dynamic-loader(ld-linux.so) 填進去的。

再比如 jump label 指令
non-PIC 的形勢是:jump printf ,意思是呼叫 printf。
PIC 的形式則是:jump[email protected],
意思是跳到 GOT 表的 index 為 printf-offset 的地方處
指示的地址去執行,
這個地址處的程式碼擺放在 .plt section

每個外部函式對應一段這樣的程式碼,其功能是呼叫dynamic-loader(ld-linux.so) 來查詢函式的地址(本例中是 printf),然後將其地址寫到 GOT 表的 index 為 printf-offset 的地方,

同時執行這個函式。這樣,第2次呼叫 printf 的時候,就會直接跳到 printf 的地址,而不必再查找了。

GOT 是 data section, 是一個 table, 除專用的幾個 entry,每個 entry 的內容可以再執行的時候修改;
PLT 是 text section, 是一段一段的 code,執行中不需要修改。
每個 target 實現 PIC 的機制不同,但大同小異。比如 MIPS 沒有 .plt, 而是叫 .stub,功能和 .plt 一樣。

可見,動態連結執行很複雜,比靜態連結執行時間長;但是,極大的節省了 size,PIC 和動態連結技術是計算機發展史上非常重要的一個里程碑。

gcc manul上面有說
-fpic        If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that -fpic does not work; in that case, recompile with -fPIC instead. (These maximums are 8k on the SPARC and 32k on the m68k and RS/6000. The 386 has no such limit.)

-fPIC       If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on the m68k, PowerPC and SPARC. Position-independent code requires special support, and therefore works only on certain machines.

關鍵在於GOT全域性偏移量表裡面的跳轉項大小。
intel處理器應該是統一4位元組,沒有問題。
powerpc上由於彙編碼或者機器碼的特殊要求,所以跳轉項分為短、長兩種。

-fpic為了節約記憶體,在GOT裡面預留了“短”長度。
而-fPIC則採用了更大的跳轉項。

相關推薦

xxx.so has text relocations. This is wasting memory and is a security risk. Please fix

 最近使用jni編譯so檔案,發現在Android M中將之前一直視為warning的text relocation升級為了error ,直接導致system.load so檔案的時候失敗。翻了網上各種資料,關於text relocation的解決辦法總結了一下: 這個錯誤的主要原因是載入.so檔案的程

java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/xxx/lib/arm/liblame.so: has text relocations

是把 tsd init ava ces cnblogs 項目配置 測試的 arm 最近在寫本地錄音轉碼過程中引入了liblame.so,我這邊用了不同系統版本的手機測試本地錄音都沒有出現問題,但是有一天,同事在測試的時候,出現了以下錯誤: 09-13 17:32:29.1

Android Vcamera target sdk》=23 has text relocations 究極解決

has text relocations 得原因是由於生成動態連結庫得問題,我們拿不到Vcamera得原始碼不能重新編譯。 但是新版得Vitamio是更新了對sdk23得支援,而報has text relocations問題得庫是libffmpeg.so(舊版 libuti

異常:This application has no explicit mapping for /error, so you are seeing this as a fallback.

prop 控制 pre fall size erro ati his xpl 出現這個異常說明了跳轉頁面的url無對應的值. 原因1: Application啟動類的位置不對.要將Application類放在最外側,即包含所有子包 原因:spring-boot會自動加載啟動

1. SpringBoot啟動後,報異常:This application has no explicit mapping for /error, so you are seeing this as a fallback.

per 視圖解析 自動加載 cati strong PE 出現 bsp AR 出現這個異常說明了跳轉頁面的url無對應的值. 原因1: Application啟動類的位置不對.要將Application類放在最外側,即包含所有子包 原因:spring-boot會自動加載啟動

ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

== running \n 就是 linux下 錯誤 var 網上 fontsize 今天在學習MySQL時候,想要將文本文件的數據導入到數據庫中,卻發現一直報錯,換了導入文本的路徑也還是同樣的錯誤,錯誤顯示ERROR 1290 (HY000): The MySQL s

AttributeError: module 'XXX' has no attribute 'xxx' && TypeError: 'module' object is not callable

AttributeError: module 'XXX' has no attribute 'xxx' && TypeError: 'module' object is not callable 最近在呼叫python的類的時候總是提示:module 'XXX' has no a

關於異常:This application has no explicit mapping for /error, so you are seeing this as a fallback.

原因1: Application啟動類的位置不對.要將Application類放在最外側,即包含所有子包 原因:spring-boot會自動載入啟動類所在包下及其子包下的所有元件. 原因2: 在springboot的配置檔案:application.yml或ap

This application has no explicit mapping for /error, so you are seeing this as a fallback

This application has no explicit mapping for /error 請求的URL無對應的對映,檢查了下,原來是controller層,忘記寫對映方法了 增加controller層對映方法 @RequestMapping("/fi

Spring-boot 報錯This application has no explicit mapping for /error, so you are seeing this as a fallb

This application has no explicit mapping for /error, so you are seeing this as a fallback. 在使用spring

This application has no explicit mapping for /error, so you are seeing this as a fallback.

出現問題的原因:    1.controller類中定義@RequestMapping("/XXX"),位址列輸入/XXX路徑名是否正確;                    2.application.properties配置檔案是否錯誤,我這裡跳轉的檢視格式為html!

quartzScheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak解決

出現此問題是由一於spring 啟動了quartz,而當tomcat 關閉的時候而沒有關閉造成的。 在web 加一個監聽器當關系的時候判斷作業是否啟動,啟動就關閉。 <!-- 作業監聽器 -->  <listener>    <listener

spring-boot啟動報錯:This application has no explicit mapping for /error, so you are seeing this as a fal

1、報錯資訊:   Whitelabel Error Page    This application has no explicit mapping for /error, so you are seeing this as a fallback.    We

error while loading shared libraries: xxx.so.x"錯誤的原因和解決辦法

exp 不想 ech cache 方案 動態鏈接庫 direct 就會 export 一般我們在Linux下執行某些外部程序的時候可能會提示找不到共享庫的錯誤, 比如: tmux: error while loading shared libraries: libe

This file's format is not supported or you don't specify a correct format. 解決辦法

版本問題 body ecif 新版 ted you cor spec asp string path = @"c:\請假統計表.xlsx"; Workbook workBook = new Workbook(); workBoo

Android6.0 UnsatisfiedLinkError couldn't find "xxx.so"

Android M 執行app時候出現如下問題: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/xxx-1/base.apk"],nativeLibra

XXX iPhone has denied the launch request.

https://blog.csdn.net/bellazhouyi/article/details/78489953 在Xcode執行 應用的時候,出現 iPhone has denied the launch request.這個問題。 目前我遇到的原因是:Signing 需要重新配置一下

Vue挖坑指南:[vue-router] Named Route 'XXX' has a default child route.

前言 OA系統,使用了路由的巢狀,希望在訪問子模組時,預設載入模組的預設路由。即為子模組設定預設路由 。 開始 我們先來看看,如何為子模組設定預設的路由。 這樣寫,會出現什麼問題呢?開啟控制檯看看。  實踐 vue-router給我們報了兩個警告,我們一個一個

This is very likely to create a memory leak. Stack trace of thread錯誤分析

1、問題描述 啟動tomcat部署專案時,報This is very likely to create a memory leak. Stack trace of thread錯誤。 29-May-2018 12:30:09.322 SEVERE [localhos

android 在佈局檔案中報錯:This text field does not specify an inputType or a hint

在安卓專案開發中,在設計專案樣式使用到EditText這個標籤時,有的時候會有警告:This text field does not specify an inputType ora hint 原因是: EditText需要指定預設輸入型別 在標籤中加入android:inpu