| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-only  | 
|---|
| 1 | 2 |  /* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com | 
|---|
| 2 | 3 |   * Copyright (c) 2016 Facebook | 
|---|
| 3 |  | - *  | 
|---|
| 4 |  | - * This program is free software; you can redistribute it and/or  | 
|---|
| 5 |  | - * modify it under the terms of version 2 of the GNU General Public  | 
|---|
| 6 |  | - * License as published by the Free Software Foundation.  | 
|---|
| 7 |  | - *  | 
|---|
| 8 |  | - * This program is distributed in the hope that it will be useful, but  | 
|---|
| 9 |  | - * WITHOUT ANY WARRANTY; without even the implied warranty of  | 
|---|
| 10 |  | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  | 
|---|
| 11 |  | - * General Public License for more details.  | 
|---|
| 12 | 4 |   */ | 
|---|
| 13 | 5 |   | 
|---|
| 14 | 6 |  #include <linux/bpf.h> | 
|---|
| .. | .. | 
|---|
| 67 | 59 |  	[BPF_STX]   = "stx", | 
|---|
| 68 | 60 |  	[BPF_ALU]   = "alu", | 
|---|
| 69 | 61 |  	[BPF_JMP]   = "jmp", | 
|---|
| 70 |  | -	[BPF_RET]   = "BUG",  | 
|---|
 | 62 | +	[BPF_JMP32] = "jmp32",  | 
|---|
| 71 | 63 |  	[BPF_ALU64] = "alu64", | 
|---|
| 72 | 64 |  }; | 
|---|
| 73 | 65 |   | 
|---|
| .. | .. | 
|---|
| 136 | 128 |  			else | 
|---|
| 137 | 129 |  				print_bpf_end_insn(verbose, cbs->private_data, insn); | 
|---|
| 138 | 130 |  		} else if (BPF_OP(insn->code) == BPF_NEG) { | 
|---|
| 139 |  | -			verbose(cbs->private_data, "(%02x) r%d = %s-r%d\n",  | 
|---|
| 140 |  | -				insn->code, insn->dst_reg,  | 
|---|
| 141 |  | -				class == BPF_ALU ? "(u32) " : "",  | 
|---|
 | 131 | +			verbose(cbs->private_data, "(%02x) %c%d = -%c%d\n",  | 
|---|
 | 132 | +				insn->code, class == BPF_ALU ? 'w' : 'r',  | 
|---|
 | 133 | +				insn->dst_reg, class == BPF_ALU ? 'w' : 'r',  | 
|---|
| 142 | 134 |  				insn->dst_reg); | 
|---|
| 143 | 135 |  		} else if (BPF_SRC(insn->code) == BPF_X) { | 
|---|
| 144 |  | -			verbose(cbs->private_data, "(%02x) %sr%d %s %sr%d\n",  | 
|---|
| 145 |  | -				insn->code, class == BPF_ALU ? "(u32) " : "",  | 
|---|
 | 136 | +			verbose(cbs->private_data, "(%02x) %c%d %s %c%d\n",  | 
|---|
 | 137 | +				insn->code, class == BPF_ALU ? 'w' : 'r',  | 
|---|
| 146 | 138 |  				insn->dst_reg, | 
|---|
| 147 | 139 |  				bpf_alu_string[BPF_OP(insn->code) >> 4], | 
|---|
| 148 |  | -				class == BPF_ALU ? "(u32) " : "",  | 
|---|
 | 140 | +				class == BPF_ALU ? 'w' : 'r',  | 
|---|
| 149 | 141 |  				insn->src_reg); | 
|---|
| 150 | 142 |  		} else { | 
|---|
| 151 |  | -			verbose(cbs->private_data, "(%02x) %sr%d %s %s%d\n",  | 
|---|
| 152 |  | -				insn->code, class == BPF_ALU ? "(u32) " : "",  | 
|---|
 | 143 | +			verbose(cbs->private_data, "(%02x) %c%d %s %d\n",  | 
|---|
 | 144 | +				insn->code, class == BPF_ALU ? 'w' : 'r',  | 
|---|
| 153 | 145 |  				insn->dst_reg, | 
|---|
| 154 | 146 |  				bpf_alu_string[BPF_OP(insn->code) >> 4], | 
|---|
| 155 |  | -				class == BPF_ALU ? "(u32) " : "",  | 
|---|
| 156 | 147 |  				insn->imm); | 
|---|
| 157 | 148 |  		} | 
|---|
| 158 | 149 |  	} else if (class == BPF_STX) { | 
|---|
| .. | .. | 
|---|
| 208 | 199 |  			 * part of the ldimm64 insn is accessible. | 
|---|
| 209 | 200 |  			 */ | 
|---|
| 210 | 201 |  			u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; | 
|---|
| 211 |  | -			bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;  | 
|---|
 | 202 | +			bool is_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD ||  | 
|---|
 | 203 | +				      insn->src_reg == BPF_PSEUDO_MAP_VALUE;  | 
|---|
| 212 | 204 |  			char tmp[64]; | 
|---|
| 213 | 205 |   | 
|---|
| 214 |  | -			if (map_ptr && !allow_ptr_leaks)  | 
|---|
 | 206 | +			if (is_ptr && !allow_ptr_leaks)  | 
|---|
| 215 | 207 |  				imm = 0; | 
|---|
| 216 | 208 |   | 
|---|
| 217 | 209 |  			verbose(cbs->private_data, "(%02x) r%d = %s\n", | 
|---|
| .. | .. | 
|---|
| 222 | 214 |  			verbose(cbs->private_data, "BUG_ld_%02x\n", insn->code); | 
|---|
| 223 | 215 |  			return; | 
|---|
| 224 | 216 |  		} | 
|---|
| 225 |  | -	} else if (class == BPF_JMP) {  | 
|---|
 | 217 | +	} else if (class == BPF_JMP32 || class == BPF_JMP) {  | 
|---|
| 226 | 218 |  		u8 opcode = BPF_OP(insn->code); | 
|---|
| 227 | 219 |   | 
|---|
| 228 | 220 |  		if (opcode == BPF_CALL) { | 
|---|
| .. | .. | 
|---|
| 246 | 238 |  		} else if (insn->code == (BPF_JMP | BPF_EXIT)) { | 
|---|
| 247 | 239 |  			verbose(cbs->private_data, "(%02x) exit\n", insn->code); | 
|---|
| 248 | 240 |  		} else if (BPF_SRC(insn->code) == BPF_X) { | 
|---|
| 249 |  | -			verbose(cbs->private_data, "(%02x) if r%d %s r%d goto pc%+d\n",  | 
|---|
| 250 |  | -				insn->code, insn->dst_reg,  | 
|---|
 | 241 | +			verbose(cbs->private_data,  | 
|---|
 | 242 | +				"(%02x) if %c%d %s %c%d goto pc%+d\n",  | 
|---|
 | 243 | +				insn->code, class == BPF_JMP32 ? 'w' : 'r',  | 
|---|
 | 244 | +				insn->dst_reg,  | 
|---|
| 251 | 245 |  				bpf_jmp_string[BPF_OP(insn->code) >> 4], | 
|---|
 | 246 | +				class == BPF_JMP32 ? 'w' : 'r',  | 
|---|
| 252 | 247 |  				insn->src_reg, insn->off); | 
|---|
| 253 | 248 |  		} else { | 
|---|
| 254 |  | -			verbose(cbs->private_data, "(%02x) if r%d %s 0x%x goto pc%+d\n",  | 
|---|
| 255 |  | -				insn->code, insn->dst_reg,  | 
|---|
 | 249 | +			verbose(cbs->private_data,  | 
|---|
 | 250 | +				"(%02x) if %c%d %s 0x%x goto pc%+d\n",  | 
|---|
 | 251 | +				insn->code, class == BPF_JMP32 ? 'w' : 'r',  | 
|---|
 | 252 | +				insn->dst_reg,  | 
|---|
| 256 | 253 |  				bpf_jmp_string[BPF_OP(insn->code) >> 4], | 
|---|
| 257 | 254 |  				insn->imm, insn->off); | 
|---|
| 258 | 255 |  		} | 
|---|