[PATCH/RFC bpf-next 03/16] bpf: split read liveness into REG_LIVE_READ64 and REG_LIVE_READ32

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In previous patch, we have split register arg type for sub-register read,
but haven't touch read liveness.

This patch further split read liveness into REG_LIVE_READ64 and
REG_LIVE_READ32. Liveness propagation code are updated accordingly.

After this split, customized actions could be defined when propagating full
register read (REG_LIVE_READ64) or sub-register read (REG_LIVE_READ32).

Signed-off-by: Jiong Wang <jiong.wang@xxxxxxxxxxxxx>
---
 include/linux/bpf_verifier.h |  9 ++++++---
 kernel/bpf/verifier.c        | 30 +++++++++++++++++++++---------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index f03c86a..27761ab 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -37,11 +37,14 @@
 /* Reg hasn't been read or written this branch. */
 #define REG_LIVE_NONE		0x0
 /* Reg was read, so we're sensitive to initial value. */
-#define REG_LIVE_READ		0x1
+#define REG_LIVE_READ32		0x1
+/* Likewise, but full 64-bit content matters. */
+#define REG_LIVE_READ64		0x2
+#define REG_LIVE_READ		(REG_LIVE_READ32 | REG_LIVE_READ64)
 /* Reg was written first, screening off later reads. */
-#define REG_LIVE_WRITTEN	0x2
+#define REG_LIVE_WRITTEN	0x4
 /* Liveness won't be updating this register anymore. */
-#define REG_LIVE_DONE		0x4
+#define REG_LIVE_DONE		0x8
 
 struct bpf_reg_state {
 	/* Ordering of fields matters.  See states_equal() */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 245bb3c..b95c438 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1126,7 +1126,7 @@ static int check_subprogs(struct bpf_verifier_env *env)
  */
 static int mark_reg_read(struct bpf_verifier_env *env,
 			 const struct bpf_reg_state *state,
-			 struct bpf_reg_state *parent)
+			 struct bpf_reg_state *parent, bool dw_read)
 {
 	bool writes = parent == state->parent; /* Observe write marks */
 
@@ -1141,7 +1141,7 @@ static int mark_reg_read(struct bpf_verifier_env *env,
 			return -EFAULT;
 		}
 		/* ... then we depend on parent's value */
-		parent->live |= REG_LIVE_READ;
+		parent->live |= dw_read ? REG_LIVE_READ64 : REG_LIVE_READ32;
 		state = parent;
 		parent = state->parent;
 		writes = true;
@@ -1170,7 +1170,7 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
 		/* We don't need to worry about FP liveness because it's read-only */
 		if (regno != BPF_REG_FP)
 			return mark_reg_read(env, &regs[regno],
-					     regs[regno].parent);
+					     regs[regno].parent, true);
 	} else {
 		/* check whether register used as dest operand can be written to */
 		if (regno == BPF_REG_FP) {
@@ -1357,7 +1357,7 @@ static int check_stack_read(struct bpf_verifier_env *env,
 			state->regs[value_regno].live |= REG_LIVE_WRITTEN;
 		}
 		mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
-			      reg_state->stack[spi].spilled_ptr.parent);
+			      reg_state->stack[spi].spilled_ptr.parent, true);
 		return 0;
 	} else {
 		int zeros = 0;
@@ -1374,7 +1374,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
 			return -EACCES;
 		}
 		mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
-			      reg_state->stack[spi].spilled_ptr.parent);
+			      reg_state->stack[spi].spilled_ptr.parent,
+			      size == BPF_REG_SIZE);
 		if (value_regno >= 0) {
 			if (zeros == size) {
 				/* any size read into register is zero extended,
@@ -2220,7 +2221,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
 		 * the whole slot to be marked as 'read'
 		 */
 		mark_reg_read(env, &state->stack[spi].spilled_ptr,
-			      state->stack[spi].spilled_ptr.parent);
+			      state->stack[spi].spilled_ptr.parent,
+			      access_size == BPF_REG_SIZE);
 	}
 	return update_stack_depth(env, state, off);
 }
@@ -6059,7 +6061,7 @@ static int propagate_liveness_reg(struct bpf_verifier_env *env,
 	if (parent_reg->live & flag || !(reg->live & flag))
 		return 0;
 
-	err = mark_reg_read(env, reg, parent_reg);
+	err = mark_reg_read(env, reg, parent_reg, flag == REG_LIVE_READ64);
 	if (err)
 		return err;
 
@@ -6092,7 +6094,12 @@ static int propagate_liveness(struct bpf_verifier_env *env,
 	regs = vstate->frame[vstate->curframe]->regs;
 	/* We don't need to worry about FP liveness because it's read-only */
 	for (i = 0; i < BPF_REG_FP; i++) {
-		err = propagate_liveness_reg(env, &regs[i], &parent_regs[i]);
+		err = propagate_liveness_reg(env, &regs[i], &parent_regs[i],
+					     REG_LIVE_READ64);
+		if (err < 0)
+			return err;
+		err = propagate_liveness_reg(env, &regs[i], &parent_regs[i],
+					     REG_LIVE_READ32);
 		if (err < 0)
 			return err;
 	}
@@ -6107,7 +6114,12 @@ static int propagate_liveness(struct bpf_verifier_env *env,
 
 			parent_reg = &parent->stack[i].spilled_ptr;
 			reg = &state->stack[i].spilled_ptr;
-			err = propagate_liveness_reg(env, reg, parent_reg);
+			err = propagate_liveness_reg(env, reg, parent_reg,
+						     REG_LIVE_READ64);
+			if (err < 0)
+				return err;
+			err = propagate_liveness_reg(env, reg, parent_reg,
+						     REG_LIVE_READ32);
 			if (err < 0)
 				return err;
 		}
-- 
2.7.4




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux