多線程 繞過mutex的保護 mutex,能夠解決線程安全的問題,但它不是萬能的。下麵的例子雖然使用了mutex,但是惡意註入了一個外部函數,導致把被mutex保護的雙向鏈表,讓一個外部的指針指向了,結果就可以通過這個外部的指針操作被保護的雙向鏈表,也就繞過了metex的保護。 例子: c++ in ...
多線程 繞過mutex的保護
mutex,能夠解決線程安全的問題,但它不是萬能的。下麵的例子雖然使用了mutex,但是惡意註入了一個外部函數,導致把被mutex保護的雙向鏈表,讓一個外部的指針指向了,結果就可以通過這個外部的指針操作被保護的雙向鏈表,也就繞過了metex的保護。
例子:
#include <list>
#include <iostream>
#include <mutex>
#include <algorithm>
#include <thread>
#include <unistd.h>
using namespace std;
//是線程安全的
class data_protect{
public:
list<int> alist{1,2};
mutex m;
public:
void add_list(int val){
//操作雙向鏈表時,加鎖了
lock_guard<mutex> g(m);
alist.push_back(val);
}
bool contains(int val){
//操作雙向鏈表時,加鎖了
lock_guard<mutex> g(m);
return find(alist.begin(), alist.end(), val) != alist.end();
}
//參數接受一個外來的函數,並把雙向鏈表傳遞給了外來的函數
template<typename Function>
void do_data(Function func){
lock_guard<mutex> g(m);
func(alist);
}
};
list<int>* unprotect_list;
//外來的函數接收到了雙向鏈表的引用,並把這個雙向鏈表暴露給外面的非保護的雙向鏈表的指針
void bad_func(list<int>& alist){
unprotect_list = &alist;
}
void gl(data_protect& dp){
dp.do_data(bad_func);
//這個插入操作沒有加鎖,所以不是線程安全的
unprotect_list->push_back(99);
}
int main(){
data_protect dp;
gl(dp);
//alist被改變了
for(auto& s : dp.alist){
cout << s << endl;
}
}