Linux�ɂ����闘�p���}���ɑ����Ă���uBerkeley Packet Filter�iBPF�j�v�ɂ��āA��b���牞�p�܂ŕ��L���Љ��A�ځB����́ABPF�v���O�����̍쐬���@�ABPF�̌��؊�AJIT�R���p�C���@�\�ɂ��ĉ�����܂��B
�@Linux�ɂ����闘�p���}���ɑ����Ă���uBerkeley Packet Filter�iBPF�j�v�ɂ��āA��b���牞�p�܂ŕ��L���Љ��A�ځuBerkeley Packet Filter�iBPF�j�����v�B�����́ABPF�̗��j��T�v�ɂ��ĉ�����A�O����BPF�̊�b�Ƃ��āALinux�ŗp������BPF�̃A�[�L�e�N�`���Ȃǂ�������܂����B
�@����́ABPF�v���O�����̍쐬���@�ABPF�̌��؊�AJIT�R���p�C���@�\�ɂ��ĉ�����܂��B
�@BPF�̃v���O�������쐬����ɂ͎�Ɉȉ��̕��@������܂��B
�@���ꂼ��ɂ��Ĉȉ��Ő������܂��B
�@��{�I�Ƀ}�N�����g���Ė��ߗ���`������@�ł��B�ˑ��W���ł����Ȃ��A�v���O�����K�͂��������ꍇ�͏\���L�p�ł��B
�@Linux�ł́A�ȉ���BPF�̖��߂Ɋւ����`������܂��B
�@�����𗘗p����BPF�̃v���O�������쐬���܂��B
�@�uinclude/uapi/linux/filter.h�v�Œ�`����Ă���A�ȉ��̃}�N���𗘗p���Ė��߂��\�����܂��B
#ifndef BPF_STMT #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k } #endif #ifndef BPF_JUMP #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k } #endif
�@�Ȃ��O��AcBPF�A�[�L�e�N�`���ɂ��Đ��������ۂ�cBPF���߂̍\���̖̂��̂��ustruct cbpf_insn�v�Ƃ��܂������ALinux�ł́ustruct sock_filter�v�Ƃ������̂ɂȂ��Ă��܂��B
�@��Ƃ��āA�uarp�p�P�b�g�ȊO���h���b�v����v�t�B���^�����O�v���O�������쐬���Ă݂܂��B�����Ƃ��āAethernet�t���[���擪���w���|�C���^���n�����Ɖ��肵�܂��B
struct sock_filter code[] = { BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), // A = P[12:14] BPF_JUMP(BPF_JMP + BPF_K + BPF_JEQ, 0x806, 0, 1), // accept if A == 0x806, otherwise jmp drop BPF_STMT(BPF_RET + BPF_K, -1), // ret -1 BPF_STMT(BPF_RET + BPF_K, 0), // drop: ret 0 };
�@����Ă��邱�Ƃ�ethernet�t���[����type�t�B�[���h��ǂݍ��݁A���̒l��0x806�ł����0��Ԃ��܂��B�����łȂ����-1�i���ۂɂ�unsigned�ŕ]������邽�߁Aunsigned int�̍ő�l�j��Ԃ��܂��B
�@�߂�l�̈Ӗ���BPF�v���O�������A�^�b�`����ӏ��ňقȂ�܂����A�p�P�b�g�t�B���^�����O�̏ꍇ�́u�߂�l����e����p�P�b�g�̍ő咷�v���Ӗ����܂��B
�@��Ɂuinclude/linux/filter.h�v�ɂ���}�N���𗘗p���ăv���O�������쐬���܂��BeBPF���߂̍\���̂́usturct bpf_insn�v�Ƃ������̂ł��B
�@��قǂ�cBPF�Ɠ����t�B���^�����O�v���O�������쐬���Ă݂܂��BR1�Ɂusk_buff�v���n�����Ɖ��肵�܂��B
struct bpf_insn code[] = { BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), // R6 = R1 BPF_LD_ABS(BPF_H, 12), // R0 = P[12:14] BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0x806, 2), // jmp drop if R0 != 0x806 BPF_MOV64_IMM(BPF_REG_0, -1), // R0 = -1 BPF_EXIT_INSN(), // ret BPF_MOV64_IMM(BPF_REG_0, 0), // drop: R0 = 0 BPF_EXIT_INSN(), // ret };
�@�����ł́uBPF_LD BPF_ABS�v���߂𗘗p���邽�߂ɁA�ŏ���R6��sk_buff�̒l�����Ă��܂��B
�EcBPF�A�Z���u��
�@Linux�̃\�[�X�Ɋ܂܂��tools/bpf��cBPF�̃A�Z���u�������݂��܂��B�ȉ��̂悤�ɂ��ăA�Z���u�����R���p�C���ł��܂��B
% git clone https://github.com/torvalds/linux % cd linux % git checkout -b v4.18 refs/tags/v4.18 # �K�v�ɉ����ăJ�[�l���o�[�W�����̎w�� % cd tools/bpf % make
�@�Ȃ��ALinux�̃\�[�X���|�W�g���̑S�N���[���͎��Ԃ�������܂��Bgit�̗������K�v�łȂ���uhttps://github.com/torvalds/linux/releases�v�������̃o�[�W�������_�E�����[�h�ł��܂��B
�@�܂��Abpf tool�̃R���p�C���ɓ������Ắubison�v�uflex�v�ulibelf�v�ubfd�v�ureadline�v���K�v�ɂȂ�܂��BUbuntu�̏ꍇ�͈ȉ��̂悤�ɂ��ăC���X�g�[���ł��܂��B
% sudo apt install bison flex libelf binutils-dev libreadline-dev
�@��قǒ��ڍ쐬����BPF�v���O�����͈ȉ��̂悤�ɏ������Ƃ��ł��܂��B
ldh [12] jne #0x806, drop ret #-1 drop: ret #0
�@���̃v���O�������ufilter.asm�v�Ƃ����t�@�C�����ŕۑ����܂��Btools/bpf�ɂ���bpf_asm�𗘗p���Ĉȉ��̂悤�ɃA�Z���u���ł��܂��B
% ./bpf_asm -c filter.asm { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 1, 0x00000806 }, { 0x06, 0, 0, 0xffffffff }, { 0x06, 0, 0, 0000000000 },
�@�����ŁA�o�͂́ustruct sock_filter�v�̃R�[�h��ɂȂ��Ă��܂��B
�@���̃A�Z���u���ŗ��p�ł���j�[���j�b�N�̐�����Linux�̃h�L�������g�ɑ��݂��܂��i"BPF engine and instruction set"�j�B
�@�܂��Atools/bpf�ɂ���bpf_dbg���g�p���邱�ƂŁAcBPF�v���O�����̃f�B�X�A�Z���u����A�u���[�N�|�C���g����̃f�o�b�O���s�Ȃǂ��\�ł��B���̎g�p���@����L�̃h�L�������g�ɂ���܂��B
�EeBPF�A�Z���u��
�@���[�U�[�X�y�[�X��eBPF�����ł���ubpf�ɁAeBPF�̃A�Z���u������уf�B�X�A�Z���u�������݂��܂��Bubpf��eBPF�A�Z���u���ŗ��p�����j�[���j�b�N���������Œ�`����Ă��܂��B
�@����܂łƓ��l�̃v���O�����͈ȉ��̂悤�ɏ������Ƃ��ł��܂��B
ldxh r2, [r1+12] mov r0, 0 jne r2, 0x0608, +1 mov r0, -1 exit
�@�Ȃ��A���̃v���O�����ł�R1���W�X�^�ɓn���ꂽ�������p�P�b�g�擪�̃|�C���^�������̂Ƃ��Ă��܂��iubpf VM�ł́uLD_ABS�v�uLD_IND�v���߂��T�|�[�g���Ă��܂���j�B
�@�ȉ��̂悤�ɂ��ăR���p�C���ł��܂��B
% git clone https://github.com/iovisor/ubpf; cd ubpf % ./bin/ubpf-assembler filter.asm a.out % hexdump -C a.out 00000000 69 12 0c 00 00 00 00 00 b7 00 00 00 00 00 00 00 |i...............| 00000010 55 02 01 00 08 06 00 00 b7 00 00 00 ff ff ff ff |U...............| 00000020 95 00 00 00 00 00 00 00 |........|
�@ubpf�A�Z���u���̏o�͂̓o�C�i���ɂȂ�܂��B
�@�Ȃ��A���Ƃ��Ƃ��̃A�Z���u���́Aubpf VM�̃e�X�g�p�r�ɍ쐬���ꂽ���̂ł��BLinux�Ŏg�p�����eBPF�v���O����������ړI�ɂ������̂ł͂���܂���B
�@tcpdump�ilibpcap�j�ɂ͍����x���̃t�B���^�[����cBPF�ɃR���p�C������@�\������܂��B�t�B���^�[���Ɋւ���h�L�������g�́uManpage of PCAP-FILTER�v�ɂ���܂��B
�@�utcpdump -d�v�𗘗p���ăt�B���^�[�����R���p�C���ł��܂��B�Ⴆ�A����܂łƓ����悤��arp�̂ݎt����t�B���^�[�͈ȉ��̂悤�ɂȂ�܂��B
% tcpdump -d arp (000) ldh [12] (001) jeq #0x806 jt 2 jf 3 (002) ret #262144 (003) ret #0
�@�܂��utcpdump -dd�v�Łustruct sock_filter�v�̃R�[�h��邱�Ƃ��ł��܂��B
% tcpdump -dd arp { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 1, 0x00000806 }, { 0x6, 0, 0, 0x00040000 }, { 0x6, 0, 0, 0x00000000 },
�@LLVM 3.7����o�b�N�G���h�Ƃ���eBPF���lj�����AClang�𗘗p����C�̃v���O������eBPF�փR���p�C�����邱�Ƃ��\�ɂȂ�܂����B���ꂪ����BPF�v���O�������쐬���邽�߂̍ł��嗬�ȕ��@�ł��B
�@���܂łƓ��l�̃v���O�����͈ȉ��̂悤�ɏ������Ƃ��ł��܂��B
�@�Ȃ��A�����ł͊ȒP�ɂ��邽�߂Ɉ����Ƃ��ăp�P�b�g�ڎ���Ă��܂����A���ۂ̃p�P�b�g�t�B���^�����O�ł�eBPF�ɓn���������́ustruct __sk_buff�v�ł��i���̃f�[�^�\���̓J�[�l���Ŏ��ۂɗ��p�����usk_buff�v�ł͂Ȃ��A�^���I�ȃf�[�^�\���ł��B���̂��Ƃ̏ڍׂ͌��؊�̐����̍ۂɍĂѐG��܂��j�B
int f(char *packet) { short type = *(short *)(packet + 12); if (type == 0x0608) { // big endian return -1; } return 0; }
�@�ȉ��̃R�}���h�ŃR���p�C�����܂��B���ʂ�elf�o�C�i���ɂȂ�܂��B
% clang -O3 -c -target bpf -o filter.o filter.c % readelf -x .text filter.o Hex dump of section '.text': 0x00000000 69110c00 00000000 b7000000 ffffffff i............... 0x00000010 15010100 08060000 b7000000 00000000 ................ 0x00000020 95000000 00000000 ........
�@��قǂ�ubpf��disassenbler�𗘗p���邱�ƂŁA�A�Z���u���̃R�[�h���m�F�ł��܂��B
% objcopy -I elf64-little -O binary filter.o filter.bin % ./ubpf/bin/ubpf-disassembler filter.bin filter.s % cat filter.s ldxh r1, [r1+12] mov r0, 0xffffffff jeq r1, 0x608, +1 mov r0, 0x0 exit
�@���ӓ_�Ƃ��āAC�̃v���O������eBPF�փR���p�C���ł��邱�ƂƁA����eBPF�v���O�������J�[�l�����̌��؊���p�X���邩�ǂ����͑S���̕ʖ��ł��BLinux��eBPF�삳���邽�߂ɂ�C���ōl�����Ȃ���Ȃ�Ȃ����Ƃ����X���݂��܂��B
�@�܂��AClang�ŃR���p�C�������I�u�W�F�N�g��ELF�o�C�i���ƂȂ�܂����A���ۂ̗��p�ɓ������Ă͂���ELF�o�C�i�������[�h���邽�߂̃��[�_�[���K�v�ɂȂ�܂��B
�@C�����eBPF�v���O�����쐬���T�|�[�g���邽�߂Ɋ���c�[����C�u�������p�ӂ���Ă��܂��BC�ɂ��eBPF�v���O�����̍쐬�͎���ȍ~�A���ڂ����������܂��B
�@���ȒP��BPF�̃v���O�������쐬�ł���悤�ɁA����̃v���W�F�N�g�ł�DSL����BPF�ւ̃R���p�C�����s���Ă��܂��B
�@�܂��ADSL�Ƃ͏��X�قȂ�܂����ABCC�ł�BPF�v���O�������ȒP�ɍ쐬���邽�߂�modified C����܂��B
Copyright © ITmedia, Inc. All Rights Reserved.