File Index
Files and directories
Sign in
FILE

libbpf_utils.c

File preview with syntax highlighting.

linux-6.19.14/tools/lib/bpf/libbpf_utils.c C
  1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2
  3/*
  4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
  5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
  6 * Copyright (C) 2015 Huawei Inc.
  7 * Copyright (C) 2017 Nicira, Inc.
  8 */
  9
 10#undef _GNU_SOURCE
 11#include <stdio.h>
 12#include <string.h>
 13#include <errno.h>
 14#include <inttypes.h>
 15#include <linux/kernel.h>
 16
 17#include "libbpf.h"
 18#include "libbpf_internal.h"
 19
 20#ifndef ENOTSUPP
 21#define ENOTSUPP	524
 22#endif
 23
 24/* make sure libbpf doesn't use kernel-only integer typedefs */
 25#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
 26
 27#define ERRNO_OFFSET(e)		((e) - __LIBBPF_ERRNO__START)
 28#define ERRCODE_OFFSET(c)	ERRNO_OFFSET(LIBBPF_ERRNO__##c)
 29#define NR_ERRNO	(__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
 30
 31static const char *libbpf_strerror_table[NR_ERRNO] = {
 32	[ERRCODE_OFFSET(LIBELF)]	= "Something wrong in libelf",
 33	[ERRCODE_OFFSET(FORMAT)]	= "BPF object format invalid",
 34	[ERRCODE_OFFSET(KVERSION)]	= "'version' section incorrect or lost",
 35	[ERRCODE_OFFSET(ENDIAN)]	= "Endian mismatch",
 36	[ERRCODE_OFFSET(INTERNAL)]	= "Internal error in libbpf",
 37	[ERRCODE_OFFSET(RELOC)]		= "Relocation failed",
 38	[ERRCODE_OFFSET(VERIFY)]	= "Kernel verifier blocks program loading",
 39	[ERRCODE_OFFSET(PROG2BIG)]	= "Program too big",
 40	[ERRCODE_OFFSET(KVER)]		= "Incorrect kernel version",
 41	[ERRCODE_OFFSET(PROGTYPE)]	= "Kernel doesn't support this program type",
 42	[ERRCODE_OFFSET(WRNGPID)]	= "Wrong pid in netlink message",
 43	[ERRCODE_OFFSET(INVSEQ)]	= "Invalid netlink sequence",
 44	[ERRCODE_OFFSET(NLPARSE)]	= "Incorrect netlink message parsing",
 45};
 46
 47int libbpf_strerror(int err, char *buf, size_t size)
 48{
 49	int ret;
 50
 51	if (!buf || !size)
 52		return libbpf_err(-EINVAL);
 53
 54	err = err > 0 ? err : -err;
 55
 56	if (err < __LIBBPF_ERRNO__START) {
 57		ret = strerror_r(err, buf, size);
 58		buf[size - 1] = '\0';
 59		return libbpf_err_errno(ret);
 60	}
 61
 62	if (err < __LIBBPF_ERRNO__END) {
 63		const char *msg;
 64
 65		msg = libbpf_strerror_table[ERRNO_OFFSET(err)];
 66		ret = snprintf(buf, size, "%s", msg);
 67		buf[size - 1] = '\0';
 68		/* The length of the buf and msg is positive.
 69		 * A negative number may be returned only when the
 70		 * size exceeds INT_MAX. Not likely to appear.
 71		 */
 72		if (ret >= size)
 73			return libbpf_err(-ERANGE);
 74		return 0;
 75	}
 76
 77	ret = snprintf(buf, size, "Unknown libbpf error %d", err);
 78	buf[size - 1] = '\0';
 79	if (ret >= size)
 80		return libbpf_err(-ERANGE);
 81	return libbpf_err(-ENOENT);
 82}
 83
 84const char *libbpf_errstr(int err)
 85{
 86	static __thread char buf[12];
 87
 88	if (err > 0)
 89		err = -err;
 90
 91	switch (err) {
 92	case -E2BIG:		return "-E2BIG";
 93	case -EACCES:		return "-EACCES";
 94	case -EADDRINUSE:	return "-EADDRINUSE";
 95	case -EADDRNOTAVAIL:	return "-EADDRNOTAVAIL";
 96	case -EAGAIN:		return "-EAGAIN";
 97	case -EALREADY:		return "-EALREADY";
 98	case -EBADF:		return "-EBADF";
 99	case -EBADFD:		return "-EBADFD";
100	case -EBUSY:		return "-EBUSY";
101	case -ECANCELED:	return "-ECANCELED";
102	case -ECHILD:		return "-ECHILD";
103	case -EDEADLK:		return "-EDEADLK";
104	case -EDOM:		return "-EDOM";
105	case -EEXIST:		return "-EEXIST";
106	case -EFAULT:		return "-EFAULT";
107	case -EFBIG:		return "-EFBIG";
108	case -EILSEQ:		return "-EILSEQ";
109	case -EINPROGRESS:	return "-EINPROGRESS";
110	case -EINTR:		return "-EINTR";
111	case -EINVAL:		return "-EINVAL";
112	case -EIO:		return "-EIO";
113	case -EISDIR:		return "-EISDIR";
114	case -ELOOP:		return "-ELOOP";
115	case -EMFILE:		return "-EMFILE";
116	case -EMLINK:		return "-EMLINK";
117	case -EMSGSIZE:		return "-EMSGSIZE";
118	case -ENAMETOOLONG:	return "-ENAMETOOLONG";
119	case -ENFILE:		return "-ENFILE";
120	case -ENODATA:		return "-ENODATA";
121	case -ENODEV:		return "-ENODEV";
122	case -ENOENT:		return "-ENOENT";
123	case -ENOEXEC:		return "-ENOEXEC";
124	case -ENOLINK:		return "-ENOLINK";
125	case -ENOMEM:		return "-ENOMEM";
126	case -ENOSPC:		return "-ENOSPC";
127	case -ENOTBLK:		return "-ENOTBLK";
128	case -ENOTDIR:		return "-ENOTDIR";
129	case -ENOTSUPP:		return "-ENOTSUPP";
130	case -ENOTTY:		return "-ENOTTY";
131	case -ENXIO:		return "-ENXIO";
132	case -EOPNOTSUPP:	return "-EOPNOTSUPP";
133	case -EOVERFLOW:	return "-EOVERFLOW";
134	case -EPERM:		return "-EPERM";
135	case -EPIPE:		return "-EPIPE";
136	case -EPROTO:		return "-EPROTO";
137	case -EPROTONOSUPPORT:	return "-EPROTONOSUPPORT";
138	case -ERANGE:		return "-ERANGE";
139	case -EROFS:		return "-EROFS";
140	case -ESPIPE:		return "-ESPIPE";
141	case -ESRCH:		return "-ESRCH";
142	case -ETXTBSY:		return "-ETXTBSY";
143	case -EUCLEAN:		return "-EUCLEAN";
144	case -EXDEV:		return "-EXDEV";
145	default:
146		snprintf(buf, sizeof(buf), "%d", err);
147		return buf;
148	}
149}
150
151static inline __u32 get_unaligned_be32(const void *p)
152{
153	__be32 val;
154
155	memcpy(&val, p, sizeof(val));
156	return be32_to_cpu(val);
157}
158
159static inline void put_unaligned_be32(__u32 val, void *p)
160{
161	__be32 be_val = cpu_to_be32(val);
162
163	memcpy(p, &be_val, sizeof(be_val));
164}
165
166#define SHA256_BLOCK_LENGTH 64
167#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
168#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
169#define Sigma_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22))
170#define Sigma_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25))
171#define sigma_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3))
172#define sigma_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10))
173
174static const __u32 sha256_K[64] = {
175	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
176	0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
177	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
178	0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
179	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
180	0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
181	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
182	0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
183	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
184	0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
185	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
186};
187
188#define SHA256_ROUND(i, a, b, c, d, e, f, g, h)                                \
189	{                                                                      \
190		__u32 tmp = h + Sigma_1(e) + Ch(e, f, g) + sha256_K[i] + w[i]; \
191		d += tmp;                                                      \
192		h = tmp + Sigma_0(a) + Maj(a, b, c);                           \
193	}
194
195static void sha256_blocks(__u32 state[8], const __u8 *data, size_t nblocks)
196{
197	while (nblocks--) {
198		__u32 a = state[0];
199		__u32 b = state[1];
200		__u32 c = state[2];
201		__u32 d = state[3];
202		__u32 e = state[4];
203		__u32 f = state[5];
204		__u32 g = state[6];
205		__u32 h = state[7];
206		__u32 w[64];
207		int i;
208
209		for (i = 0; i < 16; i++)
210			w[i] = get_unaligned_be32(&data[4 * i]);
211		for (; i < ARRAY_SIZE(w); i++)
212			w[i] = sigma_1(w[i - 2]) + w[i - 7] +
213			       sigma_0(w[i - 15]) + w[i - 16];
214		for (i = 0; i < ARRAY_SIZE(w); i += 8) {
215			SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
216			SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
217			SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
218			SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
219			SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
220			SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
221			SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
222			SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
223		}
224		state[0] += a;
225		state[1] += b;
226		state[2] += c;
227		state[3] += d;
228		state[4] += e;
229		state[5] += f;
230		state[6] += g;
231		state[7] += h;
232		data += SHA256_BLOCK_LENGTH;
233	}
234}
235
236void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH])
237{
238	__u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
239			   0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
240	const __be64 bitcount = cpu_to_be64((__u64)len * 8);
241	__u8 final_data[2 * SHA256_BLOCK_LENGTH] = { 0 };
242	size_t final_len = len % SHA256_BLOCK_LENGTH;
243	int i;
244
245	sha256_blocks(state, data, len / SHA256_BLOCK_LENGTH);
246
247	memcpy(final_data, data + len - final_len, final_len);
248	final_data[final_len] = 0x80;
249	final_len = roundup(final_len + 9, SHA256_BLOCK_LENGTH);
250	memcpy(&final_data[final_len - 8], &bitcount, 8);
251
252	sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH);
253
254	for (i = 0; i < ARRAY_SIZE(state); i++)
255		put_unaligned_be32(state[i], &out[4 * i]);
256}
~/ Read-only file preview.