kernel/bpf/fixups.c

Source file repositories/reference/linux-study-clean/kernel/bpf/fixups.c

File Facts

System
Linux kernel
Corpus path
kernel/bpf/fixups.c
Extension
.c
Size
79943 bytes
Lines
2597
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) {
			if (insn->imm == BPF_CMPXCHG)
				return BPF_REG_0;
			else if (insn->imm == BPF_LOAD_ACQ)
				return insn->dst_reg;
			else if (insn->imm & BPF_FETCH)
				return insn->src_reg;
		}
		return -1;
	default:
		return insn->dst_reg;
	}
}

/* Return TRUE if INSN has defined any 32-bit value explicitly. */
static bool insn_has_def32(struct bpf_insn *insn)
{
	int dst_reg = insn_def_regno(insn);

	if (dst_reg == -1)
		return false;

	return !bpf_is_reg64(insn, dst_reg, NULL, DST_OP);
}

static int kfunc_desc_cmp_by_imm_off(const void *a, const void *b)
{
	const struct bpf_kfunc_desc *d0 = a;
	const struct bpf_kfunc_desc *d1 = b;

	if (d0->imm != d1->imm)
		return d0->imm < d1->imm ? -1 : 1;
	if (d0->offset != d1->offset)
		return d0->offset < d1->offset ? -1 : 1;
	return 0;
}

const struct btf_func_model *
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
			 const struct bpf_insn *insn)
{
	const struct bpf_kfunc_desc desc = {
		.imm = insn->imm,
		.offset = insn->off,
	};
	const struct bpf_kfunc_desc *res;
	struct bpf_kfunc_desc_tab *tab;

	tab = prog->aux->kfunc_tab;
	res = bsearch(&desc, tab->descs, tab->nr_descs,
		      sizeof(tab->descs[0]), kfunc_desc_cmp_by_imm_off);

	return res ? &res->func_model : NULL;
}

static int set_kfunc_desc_imm(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc)
{
	unsigned long call_imm;

	if (bpf_jit_supports_far_kfunc_call()) {
		call_imm = desc->func_id;
	} else {
		call_imm = BPF_CALL_IMM(desc->addr);
		/* Check whether the relative offset overflows desc->imm */
		if ((unsigned long)(s32)call_imm != call_imm) {
			verbose(env, "address of kernel func_id %u is out of range\n",
				desc->func_id);
			return -EINVAL;
		}
	}
	desc->imm = call_imm;
	return 0;
}

static int sort_kfunc_descs_by_imm_off(struct bpf_verifier_env *env)
{
	struct bpf_kfunc_desc_tab *tab;
	int i, err;

	tab = env->prog->aux->kfunc_tab;
	if (!tab)
		return 0;

	for (i = 0; i < tab->nr_descs; i++) {
		err = set_kfunc_desc_imm(env, &tab->descs[i]);
		if (err)
			return err;
	}

	sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),

Annotation

Implementation Notes