Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cd3675e authored by Chema Gonzalez's avatar Chema Gonzalez Committed by David S. Miller
Browse files

filter: added BPF random opcode



Added a new ancillary load (bpf call in eBPF parlance) that produces
a 32-bit random number. We are implementing it as an ancillary load
(instead of an ISA opcode) because (a) it is simpler, (b) allows easy
JITing, and (c) seems more in line with generic ISAs that do not have
"get a random number" as a instruction, but as an OS call.

The main use for this ancillary load is to perform random packet sampling.

Signed-off-by: default avatarChema Gonzalez <chema@google.com>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Acked-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5a4ae5f6
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -281,6 +281,7 @@ Possible BPF extensions are shown in the following table:
  cpu                                   raw_smp_processor_id()
  vlan_tci                              vlan_tx_tag_get(skb)
  vlan_pr                               vlan_tx_tag_present(skb)
  rand                                  prandom_u32()

These extensions can also be prefixed with '#'.
Examples for low-level BPF:
@@ -308,6 +309,18 @@ Examples for low-level BPF:
  ret #-1
  drop: ret #0

** icmp random packet sampling, 1 in 4
  ldh [12]
  jne #0x800, drop
  ldb [23]
  jneq #1, drop
  # get a random uint32 number
  ld rand
  mod #4
  jneq #1, drop
  ret #-1
  drop: ret #0

** SECCOMP filter example:

  ld [4]                  /* offsetof(struct seccomp_data, arch) */
+1 −0
Original line number Diff line number Diff line
@@ -223,6 +223,7 @@ enum {
	BPF_S_ANC_VLAN_TAG,
	BPF_S_ANC_VLAN_TAG_PRESENT,
	BPF_S_ANC_PAY_OFFSET,
	BPF_S_ANC_RANDOM,
};

#endif /* __LINUX_FILTER_H__ */
+2 −1
Original line number Diff line number Diff line
@@ -130,7 +130,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
#define SKF_AD_VLAN_TAG	44
#define SKF_AD_VLAN_TAG_PRESENT 48
#define SKF_AD_PAY_OFFSET	52
#define SKF_AD_MAX	56
#define SKF_AD_RANDOM	56
#define SKF_AD_MAX	60
#define SKF_NET_OFF   (-0x100000)
#define SKF_LL_OFF    (-0x200000)

+12 −0
Original line number Diff line number Diff line
@@ -643,6 +643,12 @@ static u64 __get_raw_cpu_id(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
	return raw_smp_processor_id();
}

/* note that this only generates 32-bit random numbers */
static u64 __get_random_u32(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
{
	return (u64)prandom_u32();
}

/* Register mappings for user programs. */
#define A_REG		0
#define X_REG		7
@@ -779,6 +785,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
	case SKF_AD_OFF + SKF_AD_NLATTR:
	case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
	case SKF_AD_OFF + SKF_AD_CPU:
	case SKF_AD_OFF + SKF_AD_RANDOM:
		/* arg1 = ctx */
		insn->code = BPF_ALU64 | BPF_MOV | BPF_X;
		insn->a_reg = ARG1_REG;
@@ -812,6 +819,9 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
		case SKF_AD_OFF + SKF_AD_CPU:
			insn->imm = __get_raw_cpu_id - __bpf_call_base;
			break;
		case SKF_AD_OFF + SKF_AD_RANDOM:
			insn->imm = __get_random_u32 - __bpf_call_base;
			break;
		}
		break;

@@ -1362,6 +1372,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
			ANCILLARY(VLAN_TAG);
			ANCILLARY(VLAN_TAG_PRESENT);
			ANCILLARY(PAY_OFFSET);
			ANCILLARY(RANDOM);
			}

			/* ancillary operation unknown or unsupported */
@@ -1746,6 +1757,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
		[BPF_S_ANC_VLAN_TAG]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_PAY_OFFSET]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_RANDOM]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_LD_W_LEN]	= BPF_LD|BPF_W|BPF_LEN,
		[BPF_S_LD_W_IND]	= BPF_LD|BPF_W|BPF_IND,
		[BPF_S_LD_H_IND]	= BPF_LD|BPF_H|BPF_IND,
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ extern void yyerror(const char *str);
"#"?("cpu")	{ return K_CPU; }
"#"?("vlan_tci") { return K_VLANT; }
"#"?("vlan_pr")	{ return K_VLANP; }
"#"?("rand")	{ return K_RAND; }

":"		{ return ':'; }
","		{ return ','; }
Loading