デバイスマネージャーから、「HID準拠タッチスクリーン」を無効化する
デバイスマネージャーから、「HID準拠タッチスクリーン」を無効化する
gccで、スレッド間で同じメモリを同時にアクセスしてる人を探してぶっ殺したい。
そのためにはgccの TSAN(Thread Sanitizer)機能を使う
#include <pthread.h> #include <stdio.h> volatile long long A=0; void *gettidtest( void *arg ) { int number = (int)(long) arg; long long i; printf("thread=%d start\n", number); for(i=0;i<1000000LL;i++){ A++; // 排他制御なし // __atomic_add_fetch( &A, 1, __ATOMIC_RELAXED ); // アトミック加算 } printf("thread=%d end\n", number); return NULL; } int main( int argc, char **argv ) { int i; pthread_t p[10]={}; for(i=0;i<10;i++){ pthread_create( &p[i], NULL, gettidtest, (void*)(long)i ); } for(i=0;i<10;i++){ pthread_join( p[i], NULL ); } printf("A=%lld\n",A); return 0; }
$ gcc -g -fsanitize=thread thread.c
競合したところを教えてくれる
gccで、スタックを破壊している人を探してぶっ殺したい。
#include <stdio.h> #include <string.h> void fn1() { int c=0; // intは4バイト。5~12で静かに破壊。13以上でSegv memset(&c, 0x55, 16); // memsetが最適化で消えないように printf("c=0x%x\n", c); } int main() { fn1(); return 0; }
$ gcc -g -fstack-protector-all stack.c $ ./a.out c=0x55555555 *** stack smashing detected ***: terminated Aborted (core dumped)
スタックを破壊するとAbortしてくれる。 ulimitを設定しておけばcoreも吐く。
ただし、「マジックナンバーを敷き詰めておいて、誰かが破壊したあとに照合して検知する」という方法らしいので、派手に破壊されたときはcoreを見ても意味がない。
-fsanitize=address でもスタックオーバーフローは検知してくれるしこれで検知できたときはスタックの中身がピンピンしてるので、 -fstack-protector は使わないかも
依存ライブラリが無いので、ASANが使えない化石みたいに古い環境なら利用価値があるかも
gccで、配列の範囲を超えてアクセスしてる人を探してぶっ殺したい - 揮発性のメモ2
gccで、構造体の中の配列の範囲を超えてアクセスしてる人を探してぶっ殺したい。
しかし、 -fsanitize=address で検知できるのは「構造体をはみ出たかどうか」のみである。
配列の範囲は -fsanitize=bounds で検知する
#include <stdio.h> struct hoge { int i; char a[15]; }; int main() { struct hoge hoge = {}; printf("sizeof(hoge)=%ld\n", sizeof(struct hoge)); hoge.a[15] = 1; // ★A printf("%d\n", hoge.a[15]); hoge.a[16] = 1; // ★B printf("%d\n", hoge.a[16]); return 0; }
gcc -g -fsanitize=address sani.c
struct hoge { char a[15]; };
struct hoge のサイズは 15バイト(char 15バイト)となる。
よって、hoge.a[15] は配列を超えているし構造体もはみ出ているので検知される。
struct hoge { int i; char a[15]; };
struct hoge のサイズは 20バイト(int 4バイト + char 15バイト + パディング 1バイト)となる。
よって、hoge.a[15] は配列を超えてはいるが構造体の中なので 検知されない。
hoge.a[16] は構造体をはみ出ているので検知される。
struct hoge { char a[15]; int i; };
struct hoge のサイズは 同じく20バイトとなる。
しかし、配列を超えても超えても次の変数があるので
hoge.a[15] も hoge.a[16] も構造体の中であるため検知されない。
sanitize=bounds ならどこの配列だろうと範囲越えをチェックできる
gcc -g -fsanitize=address -fsanitize=bounds sani.c
やったぜ
gcc -Q --help=optimizers
このコマンドで、どんなオプティマイズオプションがあるか、どれが有効になっているか を確認できる
$ gcc -Q --help=optimizers The following options control optimizations: -O<number> -Ofast -Og -Os -Oz -faggressive-loop-optimizations [enabled] -falign-functions [disabled] -falign-functions= -falign-jumps [disabled] (後略)
レジスタEBPを汎用レジスタに使わせないように指示するオプション。
レジスタEBPは本来はスタック用のポインタだけど、-O2とかの最適化オプションを指定すると勝手に使いまわされちゃって、死んだときcore見てもうまくバックトレースできないことがあって嫌なので、それを抑止する
なにも指定しないとdisabled
$ gcc -Q --help=optimizers | grep omit -fomit-frame-pointer [disabled]
-O2をつけると自動でenabledになる
$ gcc -Q --help=optimizers -O2 | grep omit -fomit-frame-pointer [enabled]
-fno-omit-frame-pointer でdisabledにおさえつける
$ gcc -Q --help=optimizers -O2 -fno-omit-frame-pointer | grep omit -fomit-frame-pointer [disabled]
gccで、配列の範囲を超えてアクセスしてる人を探してぶっ殺したい。
そのためにはgccの ASAN(Address Sanitizer)機能を使う
#include <stdio.h> int main() { char buf[15]; printf("MAIN\n"); for(int i=0; i<16; i++){ printf("%08X:buf[%d]\n", &buf[i], i); buf[i] = i; } return 0; }
配列が15個しかないのに16回まわるのではみ出る、というサンプルプログラム
MAIN 621FF520:buf[0] 621FF521:buf[1] (中略) 621FF52E:buf[14] 621FF52F:buf[15] ================================================================= ==1594509==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd621ff52f at pc 0x55660474d2aa bp 0x7ffd621ff4e0 sp 0x7ffd621ff4d8 WRITE of size 1 at 0x7ffd621ff52f thread T0 #0 0x55660474d2a9 in main /tmp/main.c:9 #1 0x7f68a29f8189 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #2 0x7f68a29f8244 in __libc_start_main_impl ../csu/libc-start.c:381 #3 0x55660474d0e0 in _start (/tmp/a.out+0x10e0) Address 0x7ffd621ff52f is located in stack of thread T0 at offset 47 in frame #0 0x55660474d1b8 in main /tmp/main.c:3 This frame has 1 object(s): [32, 47) 'buf' (line 4) <== Memory access at offset 47 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/main.c:9 in main
はみ出た時点でABORTする。 ちゃんと何行目ではみ出たかを検知している。
(はみ出なければ何も起きない)
配列をはみ出たことだけを検知したいときは bounds を使う。
またこのときは ABORTせずに適当にごまかして先に進めてしまうので、それを回避したいときは
-fno-sanitize-recover=all オプションも指定すると、そこでプログラムが終了する。
gcc -g -fno-sanitize-recover=all -fsanitize=bounds main.c
MAIN 9ED8575D:buf[0] 9ED8575E:buf[1] (中略) 9ED8576B:buf[14] 9ED8576C:buf[15] main.c:9:12: runtime error: index 15 out of bounds for type 'char [15]'
情報量が無いしcoreも吐けないので これはまあ使わない
ABORTしたときにcoreを吐かせる方法。
まずそもそもulimitでコアが出るようにした上で、環境変数ASAN_OPTIONSでcoreを吐くように設定する
$ ulimit -c unlimited $ export ASAN_OPTIONS=abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1 $ ./a.out (中略) ==1594730==ABORTING Aborted (core dumped)
吐かれたcoreには、はみ出しを検知してから実際にABORTするまでの間に ASANの関数がいっぱい挟まるので 解析利用時には最後の8~9層くらいは読み飛ばす
3倍くらい遅くなる気がする
Googleドライブで、「エラーが発生しました。」と出て同期されないとき
エラーの原因はだいたいファイルがロックされているとかの場合。
このエラーが出ると、ロックしていたアプリが終了し問題が解消しても同期は再開されない。
解消する方法は
タスクトレイの右クリックメニューから 歯車⇒「エラーリスト」をクリック
ファイルの一覧が表示されるので、右の ・・・ でアップロードさせる。
全部解消したら、同期が再開する