�@�J�[�l����BPF�̃v���O�������A�^�b�`����O�ɁA����BPF�v���O���������s���Ă����S���ǂ������A���؊��p���Č����܂��B�`�F�b�N���ڂƂ��Ă͈ȉ��̂悤�Ȃ��̂�����܂��B
�@�܂��A���؊�͕K�v�ɉ����Ĉꕔ�̖��߂̏����������s���܂��B
�@cBPF�ɂ�cBPF�̌��؊킪�AeBPF�ɂ�eBPF�̌��؊킪���݂��܂��B�܂��AeBPF�ł̓v���O�����^�C�v���ƂɌ�������e�ɍ��ق����݂��܂��B
�@�ȉ��ł͎��eBPF�̌��؊�ɂ��ĊȒP�ɐ������܂��B
�@eBPF�̌��؊��kernel/bpf/verifier.c�ɂ���܂��B�܂��Atools/testing/selftests/bpf/test_verifier.c��BPF���؊�̃e�X�g�R�[�h������܂��B
�E��1�i�K
�@���؊�̃G���g���|�C���g�́ubpf_check()�v�ł��B���؊�ł́A���߂Ɂucheck_cfg()�v�Ő[���D��T���ɂ��v���O������T�����A�ȉ����`�F�b�N���܂��B
�@�Ȃ��ABPF�v���O���������T�C�Y�ȉ��ł��邱�Ƃ́A���؊�O��BPF�V�X�e���R�[���̒i�K�Ń`�F�b�N���܂��B
�E��2�i�K
�@���̌�A���؊�́udo_check()�v�Ńv���O�����̊J�n���瓞�B�\�ȃp�X��S�Ă��ǂ�A�u�s���Ȗ��ߎ��s���Ȃ����v�������܂��B���̂��߂Ɍ��؊�͊e���W�X�^�̏�Ԃ�ǐՂ��Ă��܂��B
�@�e���W�X�^�̏�Ԃ́ustruct bpf_reg_state�v�ŊǗ�����܂��B�ubpf_reg_state�v�͈ȉ��̂悤�ȏ���ێ����܂��B
�@bpf_reg_type�Ƃ��Ĉȉ�����`����Ă��܂��B
bpf_reg_type | �Ӗ� |
---|---|
NOT_INIT | ����������� |
SCALAR_VALUE | �X�J���l�i�|�C���^�Ƃ��ĕs���Ȓl�j |
PTR_TO_CTX | �ubpf_context�v�ւ̃|�C���^ |
CONST_PTR_TO_MAP | �ustruct bpf_map�v�ւ̃|�C���^�B�|�C���^���Z�s�� |
PTR_TO_MAP_VALUEBPF | map�v�f�ւ̃|�C���^ |
PTR_TO_MAP_VALUE_OR_NULL | BPF map�v�f���邢��NULL�ւ̃|�C���^�B�|�C���^���Z�s�� |
PTR_TO_STACK | �X�^�b�N�ւ̃|�C���^ |
PTR_TO_PACKET_META | skb->data - meta_len |
PTR_TO_PACKET | skb->data |
PTR_TO_PACKET_END | skb->data + headlen�B�|�C���^���Z�s�� |
�@�v���O�����̏�����Ԃł́AR1�̌^��PTR_TO_CTX�AR10�̌^��PTR_TO_STACK�ł���A����ȊO�̃��W�X�^�̌^��NOT_INIT�ɂȂ�܂��B���߂̎��s�ɂ���āA���W�X�^�̏�Ԃ͕ω����܂��B
�@�ȉ��Ɋ����������܂��B
�@�����̏�Ԃ����ɁA�udo_check()�v�̒��ł͈��̖��߂ɑ��āA���̖��߂����s�\���m�F���A���s�\�ł�����W�X�^��Ԃ��X�V���܂��B
�@�Ⴆ�AALU���߂̏ꍇ�A�ucheck_alu_op()�v�����W�X�^�̃I�y�����h������������A�\��t�B�[���h��0�ł��邩�Ȃǂ��m�F���Ă��܂��B
�@���[�h��X�g�A���߂̏ꍇ�́A�ucheck_mem_access()�v�Ő������������A�N�Z�X���s���邩���`�F�b�N���܂��B
�@���ɁA�A�N�Z�X�悪PTR_TO_CTX�̂Ƃ��A�ucheck_ctx_access()�v�ɂ����āuenv->ops->is_valid_access()�v�R�[���o�b�N�����Ă�܂��B
�@���̃R�[���o�b�N���́A�R���e�L�X�g���Ƃɐݒ肳�����ŁA����ɂ��R���e�L�X�g�ɉ����������s���܂��B
�@�Ⴆ�A�p�P�b�g�t�B���^�����O�Ŏg�p�����uBPF_PROG_TYPE_SOCKET_FILTER�v�̏ꍇ�A�Ή�����R���e�L�X�g�̌��؊�́usk_filter_verifier_ops�v�ɂȂ�܂��i�uverifier_ops�v�̃v���g�^�C�v�錾��bpf.h�ɂ���܂��j�B
�@�usk_filter_is_valid_access()�v�ŃI�t�Z�b�g�����������ǂ����i�ǂݏo���֎~�̈�ɃA�N�Z�X���Ȃ����j�A�������݂͋����ꂽ�t�B�[���h�ɑ��Ă��ǂ����ȂǂׂĂ��܂��B
�@���Ăяo���Ɋւ��Ă��A�v���O�����^�C�v���ƂɎg�p�ł�����͈قȂ邽�߁A�R�[���o�b�N���𗘗p���܂��B
�@�ucheck_helper_call()�v�ŊO�����Ăяo�����߂̃`�F�b�N�����܂��B�����ŁA�uenv->ops->get_func_proto()�v�R�[���o�b�N���Ŋ��̃v���g�^�C�v�邽�߂̊����擾���܂��B
�@�uBPF_PROG_TYPE_SOCKET_FILTER�v�̏ꍇ�A���̊��́usk_filter_func_proto()�v�ł��B���̃v���g�^�C�v�͖߂�l��������`���Ă���i���j�A���؊�͂���Ɋ�Â��Č����s���܂��B
�E���߂̏�������
�@�udo_check()�v��A���؊�ł͈ꕔ���߂����������܂��B
�@�uconvert_ctx_access()�v�ł́AeBPF�v���O�����̈����Ƃ��ēn�����R���e�L�X�g�����������܂��B
�@�Ⴆ�A�l�b�g���[�N�Ɋ֘A����eBPF�v���O�������쐬����ۂ�include/uapi/linux/bpf.h�Œ�`�����ustruct __sk_buff�v���n�������̂Ƃ��ăv���O�������쐬���܂����A�uconvert_ctx_access()�v�ł͂��́u__sk_buff�v�̃A�N�Z�X�����ۂ̃J�[�l�����̃f�[�^�\���ŗ��p�����usk_buff�v�̑Ή������t�B�[���h�ɑ���A�N�Z�X�ƂȂ�悤�ɕϊ����܂��B
�@���̂悤�ȍ\���ɂȂ��Ă��闝�R�͈ȉ��̒ʂ�ł��B�ustruct sk_buff�v�̓J�[�l�����f�[�^�\���ł���A�J�[�l���̍X�V���ƂɕύX�����\��������܂��B
�@�܂�A�ustruct sk_buff�v�𗘗p����v���O�����́usk_buff�v�̕ύX�ɔ����ďC������K�v������܂��B�p�P�b�g�t�B���^�����O�̂悤�ȁA�悭�g�p�����A�v���P�[�V�����ł��������J�[�l�����ƂɑΉ�����͖̂ʓ|�ł��B�����ŁA����Ɂu__sk_buff�v�̎g�p����Ă���܂����B
�@���؊�Łu__sk_buff�v�̃A�N�Z�X��ϊ����邱�ƂŁA�usk_buff�v�̃f�[�^�\�����ύX����Ă�BPF�̃v���O�������C������K�v�͂Ȃ��Ȃ�܂��B�܂��A���̂悤�ȍ\���ɂ��邱�ƂŁABPF�v���O�������Ɍ�����f�[�^�t�B�[���h�𐧌����邱�Ƃ��ł��܂��B�u__sk_buff�v�́uuapi�v�Ƃ��ăG�N�X�|�[�g����Ă���A����݊����������čX�V����邱�Ƃ��ۏ���Ă��܂��B
�@�Ȃ��A�R���e�L�X�g�ϊ����R�[���o�b�N���Œ�`����Ă��܂��B���ہA�usk_buff�v�̕ϊ��́ubpf_convert_ctx_access()�v�ōs���Ă��܂��B
�@�܂��A�ufixup_bpf_calls()�v�ł͊�����Ăяo�����߂��C�����Ă��܂��B
�@�uBPF_LD BPF_ABS�v�uBPF_LD BPF_IND�v���߂͂��̃^�C�~���O�������������܂��B���̏����������R�[���o�b�N���o�R�ōs���Ă���A���ۂ̏����������́ubpf_gen_ld_abs()�v�ł��B
�@�uBPF_LD BPF_ABS�v�uBPF_LD BPF_IND�v�͈ȉ��̂悤�Ȗ��߂ɏ����������Ă��܂��i�����j�B
switch (BPF_SIZE(orig->code)) { case BPF_B: *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_8_no_cache); break; case BPF_H: *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_16_no_cache); break; case BPF_W: *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_32_no_cache); break; } *insn++ = BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 2); *insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_0, BPF_REG_0); *insn++ = BPF_EXIT_INSN();
�@BPF_CALL�ŌĂ����ł͋��E�l�`�F�b�N���s���A�͈͊O�ł���u-EFAULT�v�Ƃ����l��Ԃ��܂��B
BPF_CALL_4(bpf_skb_load_helper_8, const struct sk_buff *, skb, const void *, data, int, headlen, int, offset) { u8 tmp, *ptr; const int len = sizeof(tmp); if (offset >= 0) { if (headlen �Eoffset >= len) return *(u8 *)(data + offset); if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) return tmp; } else { ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len); if (likely(ptr)) return *(u8 *)ptr; } return -EFAULT; }
�@��L�̏���������̖��߂ł́ABPF_CALL�̖߂�l���`�F�b�N���A�������ꂪ���̒l�ł���uBFP_EXIT_INSN()�v�Ńv���O�������s���I�����Ă��܂��B
�EDirect Packet Access
�@��قǎ������悤�ɁuBPF_LD BPF_ABS�v�uBPF_LD BPF_IND�v���߂͊��Ăяo���Ƃ��Ď��s����A�A�N�Z�X�͈͂��`�F�b�N����܂��B�����eBPF�v���O��������p�P�b�g�ɃA�N�Z�X����B��̕��@�ł������AXDP�ȂǍ����p�P�b�g���������߂����ʂł́A���s�̃I�[�o�[�w�b�h���傫�����Ƃ��������܂����B
�@�����ŁABPF�v���O�������璼�ڃp�P�b�g�̃f�[�^�ɃA�N�Z�X�ł���Direct Packet Access����������܂����B
�@�ȉ��ɁADirect Packet Access�𗘗p����BPF�v���O�����������܂��i�R�~�b�g���b�Z�[�W���甲���j�B
int bpf_prog(struct __sk_buff *skb) { struct iphdr *ip; if (skb->data + sizeof(struct iphdr) + ETH_HLEN > skb->data_end) /* packet too small */ return 0; ip = skb->data + ETH_HLEN; /* access IP header fields with direct loads */ if (ip->version != 4 |ip->saddr == 0x7f000001) return 1; ... }
�@���̃v���O�����ł́A�ustruct iphdr *ip�v�𗘗p���āAsk_buff�̃f�[�^�ɒ��ڃA�N�Z�X���Ă��܂��B���̃v���O�����̎��s�����؊킪�����邩�炭��́Abpf_reg_type�́uTR_TO_PACKET�v�uPTR_TO_PACKET_END�v�^�ɂ���܂��B
�@�܂��A�uskb->data�v�̒l�����W�X�^�Ƀ��[�h����Ƃ��A�uis_valid_access()�v���ɂ���āA���̌^�́uPTR_TO_PACKET�v�ɂȂ�܂��B
�@���l�Ɂuskb->data_end�v�����[�h����ƁA���̌^�́uPTR_TO_PACKET_END�v�ɂȂ�܂��B�uskb->data�v����uskb->data_end�v�܂ł��A�v���O�������A�N�Z�X�ł���͈͂ł��B
�@���̌�A�uskb->data + sizeof(struct iphdr) + ETH_HLEN > skb->data_end�v�̔�r���s���ہA�udst_reg->type == PTR_TO_PACKET_END && src_reg->type == PTR_TO_PACKET�v���������A���؊�ł́ufind_good_pkt_pionters()�v���Ă�܂��B
�@���̊��ŁA�uif (skb->data + sizeof(struct iphdr) + ETH_HLEN > skb->data_end)�v�̏��������藧���Ȃ�����ł́A�uskb->data�v����uskb->data + ETH_HLEN + sizeof(sturct iphdr)�v�͈̔͂Ɋւ��Ă̓A�N�Z�X������悤�ɁA�ubpf_reg_state�v�́urange�v���X�V����܂��B
�@���̂悤�ɁADirect Packet Access�ł͌��؊�ŃA�N�Z�X�̈��S�����ۏ��ꂽ��Œ��ڃp�P�b�g�ɃA�N�Z�X���܂��B
�@�Ȃ��Askbuff�̃f�[�^�͓����I�Ƀt���O�����g���Ă���ꍇ������܂��B�p�P�b�g�̑S�f�[�^�ɑ���direct access���ł���悤�ɁA�t���O�����g���Ă���skbuff��1�ɂ܂Ƃ߂�w���p�[�������݂��܂��B
�@���Ȃ݂ɁADirect Packet Access�����p�ł���BPF�v���O�����^�C�v�͉��L�̂悤�ɂȂ�܂��B
�@BPF_PROG_TYPE_SOCKET_FILTER�ł�Direct Packet Access�͂ł��܂���B
�@cBPF�̌��؊��net/core/filter.c�́ucheck_classic()�v�ł��BcBPF��eBPF�Ɣ�׃V���v���ȃA�[�L�e�N�`���ł��邽�߁A���؊펩�̂�eBPF���������ƒP���ł��B
�@�܂�cBPF��eBPF�֕ϊ�����Ď��s����܂����AeBPF�ւ̕ϊ��̑O�ɁA���̌��؊킪���s����܂��B�ϊ����eBPF�̌��؊킪�Ă�邱�Ƃ͂���܂���B
�@seccomp�͒ʏ��cBPF�̌��؊�ɉ����Aseccomp�p�̌��؊��p���ăv���O�����������܂��B����Ɋւ��Ă�seccomp���������ۂɍĂѐG��܂��B
Copyright © ITmedia, Inc. All Rights Reserved.