diff options
author | Andrey Ignatov <rdna@fb.com> | 2018-03-30 18:08:01 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-03-30 20:15:05 -0400 |
commit | d7be143b67c2cf99bf93279217b1cf93a1e8a6b1 (patch) | |
tree | 6bc585808af68691fcd4f7830f3fee797f3e8764 /tools/lib | |
parent | 5e43f899b03a3492ce5fc44e8900becb04dae9c0 (diff) |
libbpf: Support expected_attach_type at prog load
Support setting `expected_attach_type` at prog load time in both
`bpf/bpf.h` and `bpf/libbpf.h`.
Since both headers already have API to load programs, new functions are
added not to break backward compatibility for existing ones:
* `bpf_load_program_xattr()` is added to `bpf/bpf.h`;
* `bpf_prog_load_xattr()` is added to `bpf/libbpf.h`.
Both new functions accept structures, `struct bpf_load_program_attr` and
`struct bpf_prog_load_attr` correspondingly, where new fields can be
added in the future w/o changing the API.
Standard `_xattr` suffix is used to name the new API functions.
Since `bpf_load_program_name()` is not used as heavily as
`bpf_load_program()`, it was removed in favor of more generic
`bpf_load_program_xattr()`.
Signed-off-by: Andrey Ignatov <rdna@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/bpf/bpf.c | 44 | ||||
-rw-r--r-- | tools/lib/bpf/bpf.h | 17 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 105 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 8 |
4 files changed, 128 insertions, 46 deletions
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index e0500055f1a6..acbb3f8b3bec 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c | |||
@@ -146,26 +146,30 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, | |||
146 | -1); | 146 | -1); |
147 | } | 147 | } |
148 | 148 | ||
149 | int bpf_load_program_name(enum bpf_prog_type type, const char *name, | 149 | int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, |
150 | const struct bpf_insn *insns, | 150 | char *log_buf, size_t log_buf_sz) |
151 | size_t insns_cnt, const char *license, | ||
152 | __u32 kern_version, char *log_buf, | ||
153 | size_t log_buf_sz) | ||
154 | { | 151 | { |
155 | int fd; | ||
156 | union bpf_attr attr; | 152 | union bpf_attr attr; |
157 | __u32 name_len = name ? strlen(name) : 0; | 153 | __u32 name_len; |
154 | int fd; | ||
155 | |||
156 | if (!load_attr) | ||
157 | return -EINVAL; | ||
158 | |||
159 | name_len = load_attr->name ? strlen(load_attr->name) : 0; | ||
158 | 160 | ||
159 | bzero(&attr, sizeof(attr)); | 161 | bzero(&attr, sizeof(attr)); |
160 | attr.prog_type = type; | 162 | attr.prog_type = load_attr->prog_type; |
161 | attr.insn_cnt = (__u32)insns_cnt; | 163 | attr.expected_attach_type = load_attr->expected_attach_type; |
162 | attr.insns = ptr_to_u64(insns); | 164 | attr.insn_cnt = (__u32)load_attr->insns_cnt; |
163 | attr.license = ptr_to_u64(license); | 165 | attr.insns = ptr_to_u64(load_attr->insns); |
166 | attr.license = ptr_to_u64(load_attr->license); | ||
164 | attr.log_buf = ptr_to_u64(NULL); | 167 | attr.log_buf = ptr_to_u64(NULL); |
165 | attr.log_size = 0; | 168 | attr.log_size = 0; |
166 | attr.log_level = 0; | 169 | attr.log_level = 0; |
167 | attr.kern_version = kern_version; | 170 | attr.kern_version = load_attr->kern_version; |
168 | memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); | 171 | memcpy(attr.prog_name, load_attr->name, |
172 | min(name_len, BPF_OBJ_NAME_LEN - 1)); | ||
169 | 173 | ||
170 | fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); | 174 | fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); |
171 | if (fd >= 0 || !log_buf || !log_buf_sz) | 175 | if (fd >= 0 || !log_buf || !log_buf_sz) |
@@ -184,8 +188,18 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, | |||
184 | __u32 kern_version, char *log_buf, | 188 | __u32 kern_version, char *log_buf, |
185 | size_t log_buf_sz) | 189 | size_t log_buf_sz) |
186 | { | 190 | { |
187 | return bpf_load_program_name(type, NULL, insns, insns_cnt, license, | 191 | struct bpf_load_program_attr load_attr; |
188 | kern_version, log_buf, log_buf_sz); | 192 | |
193 | memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); | ||
194 | load_attr.prog_type = type; | ||
195 | load_attr.expected_attach_type = 0; | ||
196 | load_attr.name = NULL; | ||
197 | load_attr.insns = insns; | ||
198 | load_attr.insns_cnt = insns_cnt; | ||
199 | load_attr.license = license; | ||
200 | load_attr.kern_version = kern_version; | ||
201 | |||
202 | return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz); | ||
189 | } | 203 | } |
190 | 204 | ||
191 | int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, | 205 | int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index ee59342c6f42..39f6a0d64a3b 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h | |||
@@ -41,13 +41,20 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, | |||
41 | int key_size, int inner_map_fd, int max_entries, | 41 | int key_size, int inner_map_fd, int max_entries, |
42 | __u32 map_flags); | 42 | __u32 map_flags); |
43 | 43 | ||
44 | struct bpf_load_program_attr { | ||
45 | enum bpf_prog_type prog_type; | ||
46 | enum bpf_attach_type expected_attach_type; | ||
47 | const char *name; | ||
48 | const struct bpf_insn *insns; | ||
49 | size_t insns_cnt; | ||
50 | const char *license; | ||
51 | __u32 kern_version; | ||
52 | }; | ||
53 | |||
44 | /* Recommend log buffer size */ | 54 | /* Recommend log buffer size */ |
45 | #define BPF_LOG_BUF_SIZE (256 * 1024) | 55 | #define BPF_LOG_BUF_SIZE (256 * 1024) |
46 | int bpf_load_program_name(enum bpf_prog_type type, const char *name, | 56 | int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, |
47 | const struct bpf_insn *insns, | 57 | char *log_buf, size_t log_buf_sz); |
48 | size_t insns_cnt, const char *license, | ||
49 | __u32 kern_version, char *log_buf, | ||
50 | size_t log_buf_sz); | ||
51 | int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, | 58 | int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
52 | size_t insns_cnt, const char *license, | 59 | size_t insns_cnt, const char *license, |
53 | __u32 kern_version, char *log_buf, | 60 | __u32 kern_version, char *log_buf, |
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 64a8fc384186..48e3e743ebf7 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -203,6 +203,8 @@ struct bpf_program { | |||
203 | struct bpf_object *obj; | 203 | struct bpf_object *obj; |
204 | void *priv; | 204 | void *priv; |
205 | bpf_program_clear_priv_t clear_priv; | 205 | bpf_program_clear_priv_t clear_priv; |
206 | |||
207 | enum bpf_attach_type expected_attach_type; | ||
206 | }; | 208 | }; |
207 | 209 | ||
208 | struct bpf_map { | 210 | struct bpf_map { |
@@ -1162,21 +1164,31 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
1162 | } | 1164 | } |
1163 | 1165 | ||
1164 | static int | 1166 | static int |
1165 | load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns, | 1167 | load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type, |
1166 | int insns_cnt, char *license, u32 kern_version, int *pfd) | 1168 | const char *name, struct bpf_insn *insns, int insns_cnt, |
1169 | char *license, u32 kern_version, int *pfd) | ||
1167 | { | 1170 | { |
1168 | int ret; | 1171 | struct bpf_load_program_attr load_attr; |
1169 | char *log_buf; | 1172 | char *log_buf; |
1173 | int ret; | ||
1170 | 1174 | ||
1171 | if (!insns || !insns_cnt) | 1175 | memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); |
1176 | load_attr.prog_type = type; | ||
1177 | load_attr.expected_attach_type = expected_attach_type; | ||
1178 | load_attr.name = name; | ||
1179 | load_attr.insns = insns; | ||
1180 | load_attr.insns_cnt = insns_cnt; | ||
1181 | load_attr.license = license; | ||
1182 | load_attr.kern_version = kern_version; | ||
1183 | |||
1184 | if (!load_attr.insns || !load_attr.insns_cnt) | ||
1172 | return -EINVAL; | 1185 | return -EINVAL; |
1173 | 1186 | ||
1174 | log_buf = malloc(BPF_LOG_BUF_SIZE); | 1187 | log_buf = malloc(BPF_LOG_BUF_SIZE); |
1175 | if (!log_buf) | 1188 | if (!log_buf) |
1176 | pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); | 1189 | pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); |
1177 | 1190 | ||
1178 | ret = bpf_load_program_name(type, name, insns, insns_cnt, license, | 1191 | ret = bpf_load_program_xattr(&load_attr, log_buf, BPF_LOG_BUF_SIZE); |
1179 | kern_version, log_buf, BPF_LOG_BUF_SIZE); | ||
1180 | 1192 | ||
1181 | if (ret >= 0) { | 1193 | if (ret >= 0) { |
1182 | *pfd = ret; | 1194 | *pfd = ret; |
@@ -1192,18 +1204,18 @@ load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns, | |||
1192 | pr_warning("-- BEGIN DUMP LOG ---\n"); | 1204 | pr_warning("-- BEGIN DUMP LOG ---\n"); |
1193 | pr_warning("\n%s\n", log_buf); | 1205 | pr_warning("\n%s\n", log_buf); |
1194 | pr_warning("-- END LOG --\n"); | 1206 | pr_warning("-- END LOG --\n"); |
1195 | } else if (insns_cnt >= BPF_MAXINSNS) { | 1207 | } else if (load_attr.insns_cnt >= BPF_MAXINSNS) { |
1196 | pr_warning("Program too large (%d insns), at most %d insns\n", | 1208 | pr_warning("Program too large (%zu insns), at most %d insns\n", |
1197 | insns_cnt, BPF_MAXINSNS); | 1209 | load_attr.insns_cnt, BPF_MAXINSNS); |
1198 | ret = -LIBBPF_ERRNO__PROG2BIG; | 1210 | ret = -LIBBPF_ERRNO__PROG2BIG; |
1199 | } else { | 1211 | } else { |
1200 | /* Wrong program type? */ | 1212 | /* Wrong program type? */ |
1201 | if (type != BPF_PROG_TYPE_KPROBE) { | 1213 | if (load_attr.prog_type != BPF_PROG_TYPE_KPROBE) { |
1202 | int fd; | 1214 | int fd; |
1203 | 1215 | ||
1204 | fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name, | 1216 | load_attr.prog_type = BPF_PROG_TYPE_KPROBE; |
1205 | insns, insns_cnt, license, | 1217 | load_attr.expected_attach_type = 0; |
1206 | kern_version, NULL, 0); | 1218 | fd = bpf_load_program_xattr(&load_attr, NULL, 0); |
1207 | if (fd >= 0) { | 1219 | if (fd >= 0) { |
1208 | close(fd); | 1220 | close(fd); |
1209 | ret = -LIBBPF_ERRNO__PROGTYPE; | 1221 | ret = -LIBBPF_ERRNO__PROGTYPE; |
@@ -1247,8 +1259,9 @@ bpf_program__load(struct bpf_program *prog, | |||
1247 | pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", | 1259 | pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", |
1248 | prog->section_name, prog->instances.nr); | 1260 | prog->section_name, prog->instances.nr); |
1249 | } | 1261 | } |
1250 | err = load_program(prog->type, prog->name, prog->insns, | 1262 | err = load_program(prog->type, prog->expected_attach_type, |
1251 | prog->insns_cnt, license, kern_version, &fd); | 1263 | prog->name, prog->insns, prog->insns_cnt, |
1264 | license, kern_version, &fd); | ||
1252 | if (!err) | 1265 | if (!err) |
1253 | prog->instances.fds[0] = fd; | 1266 | prog->instances.fds[0] = fd; |
1254 | goto out; | 1267 | goto out; |
@@ -1276,8 +1289,8 @@ bpf_program__load(struct bpf_program *prog, | |||
1276 | continue; | 1289 | continue; |
1277 | } | 1290 | } |
1278 | 1291 | ||
1279 | err = load_program(prog->type, prog->name, | 1292 | err = load_program(prog->type, prog->expected_attach_type, |
1280 | result.new_insn_ptr, | 1293 | prog->name, result.new_insn_ptr, |
1281 | result.new_insn_cnt, | 1294 | result.new_insn_cnt, |
1282 | license, kern_version, &fd); | 1295 | license, kern_version, &fd); |
1283 | 1296 | ||
@@ -1835,11 +1848,22 @@ BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT); | |||
1835 | BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); | 1848 | BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); |
1836 | BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); | 1849 | BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); |
1837 | 1850 | ||
1838 | #define BPF_PROG_SEC(string, type) { string, sizeof(string) - 1, type } | 1851 | static void bpf_program__set_expected_attach_type(struct bpf_program *prog, |
1852 | enum bpf_attach_type type) | ||
1853 | { | ||
1854 | prog->expected_attach_type = type; | ||
1855 | } | ||
1856 | |||
1857 | #define BPF_PROG_SEC_FULL(string, ptype, atype) \ | ||
1858 | { string, sizeof(string) - 1, ptype, atype } | ||
1859 | |||
1860 | #define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_FULL(string, ptype, 0) | ||
1861 | |||
1839 | static const struct { | 1862 | static const struct { |
1840 | const char *sec; | 1863 | const char *sec; |
1841 | size_t len; | 1864 | size_t len; |
1842 | enum bpf_prog_type prog_type; | 1865 | enum bpf_prog_type prog_type; |
1866 | enum bpf_attach_type expected_attach_type; | ||
1843 | } section_names[] = { | 1867 | } section_names[] = { |
1844 | BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), | 1868 | BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), |
1845 | BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), | 1869 | BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), |
@@ -1859,9 +1883,11 @@ static const struct { | |||
1859 | BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), | 1883 | BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), |
1860 | BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG), | 1884 | BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG), |
1861 | }; | 1885 | }; |
1886 | |||
1862 | #undef BPF_PROG_SEC | 1887 | #undef BPF_PROG_SEC |
1888 | #undef BPF_PROG_SEC_FULL | ||
1863 | 1889 | ||
1864 | static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog) | 1890 | static int bpf_program__identify_section(struct bpf_program *prog) |
1865 | { | 1891 | { |
1866 | int i; | 1892 | int i; |
1867 | 1893 | ||
@@ -1871,13 +1897,13 @@ static enum bpf_prog_type bpf_program__guess_type(struct bpf_program *prog) | |||
1871 | for (i = 0; i < ARRAY_SIZE(section_names); i++) | 1897 | for (i = 0; i < ARRAY_SIZE(section_names); i++) |
1872 | if (strncmp(prog->section_name, section_names[i].sec, | 1898 | if (strncmp(prog->section_name, section_names[i].sec, |
1873 | section_names[i].len) == 0) | 1899 | section_names[i].len) == 0) |
1874 | return section_names[i].prog_type; | 1900 | return i; |
1875 | 1901 | ||
1876 | err: | 1902 | err: |
1877 | pr_warning("failed to guess program type based on section name %s\n", | 1903 | pr_warning("failed to guess program type based on section name %s\n", |
1878 | prog->section_name); | 1904 | prog->section_name); |
1879 | 1905 | ||
1880 | return BPF_PROG_TYPE_UNSPEC; | 1906 | return -1; |
1881 | } | 1907 | } |
1882 | 1908 | ||
1883 | int bpf_map__fd(struct bpf_map *map) | 1909 | int bpf_map__fd(struct bpf_map *map) |
@@ -1977,11 +2003,30 @@ long libbpf_get_error(const void *ptr) | |||
1977 | int bpf_prog_load(const char *file, enum bpf_prog_type type, | 2003 | int bpf_prog_load(const char *file, enum bpf_prog_type type, |
1978 | struct bpf_object **pobj, int *prog_fd) | 2004 | struct bpf_object **pobj, int *prog_fd) |
1979 | { | 2005 | { |
2006 | struct bpf_prog_load_attr attr; | ||
2007 | |||
2008 | memset(&attr, 0, sizeof(struct bpf_prog_load_attr)); | ||
2009 | attr.file = file; | ||
2010 | attr.prog_type = type; | ||
2011 | attr.expected_attach_type = 0; | ||
2012 | |||
2013 | return bpf_prog_load_xattr(&attr, pobj, prog_fd); | ||
2014 | } | ||
2015 | |||
2016 | int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, | ||
2017 | struct bpf_object **pobj, int *prog_fd) | ||
2018 | { | ||
1980 | struct bpf_program *prog, *first_prog = NULL; | 2019 | struct bpf_program *prog, *first_prog = NULL; |
2020 | enum bpf_attach_type expected_attach_type; | ||
2021 | enum bpf_prog_type prog_type; | ||
1981 | struct bpf_object *obj; | 2022 | struct bpf_object *obj; |
2023 | int section_idx; | ||
1982 | int err; | 2024 | int err; |
1983 | 2025 | ||
1984 | obj = bpf_object__open(file); | 2026 | if (!attr) |
2027 | return -EINVAL; | ||
2028 | |||
2029 | obj = bpf_object__open(attr->file); | ||
1985 | if (IS_ERR(obj)) | 2030 | if (IS_ERR(obj)) |
1986 | return -ENOENT; | 2031 | return -ENOENT; |
1987 | 2032 | ||
@@ -1990,15 +2035,23 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type, | |||
1990 | * If type is not specified, try to guess it based on | 2035 | * If type is not specified, try to guess it based on |
1991 | * section name. | 2036 | * section name. |
1992 | */ | 2037 | */ |
1993 | if (type == BPF_PROG_TYPE_UNSPEC) { | 2038 | prog_type = attr->prog_type; |
1994 | type = bpf_program__guess_type(prog); | 2039 | expected_attach_type = attr->expected_attach_type; |
1995 | if (type == BPF_PROG_TYPE_UNSPEC) { | 2040 | if (prog_type == BPF_PROG_TYPE_UNSPEC) { |
2041 | section_idx = bpf_program__identify_section(prog); | ||
2042 | if (section_idx < 0) { | ||
1996 | bpf_object__close(obj); | 2043 | bpf_object__close(obj); |
1997 | return -EINVAL; | 2044 | return -EINVAL; |
1998 | } | 2045 | } |
2046 | prog_type = section_names[section_idx].prog_type; | ||
2047 | expected_attach_type = | ||
2048 | section_names[section_idx].expected_attach_type; | ||
1999 | } | 2049 | } |
2000 | 2050 | ||
2001 | bpf_program__set_type(prog, type); | 2051 | bpf_program__set_type(prog, prog_type); |
2052 | bpf_program__set_expected_attach_type(prog, | ||
2053 | expected_attach_type); | ||
2054 | |||
2002 | if (prog->idx != obj->efile.text_shndx && !first_prog) | 2055 | if (prog->idx != obj->efile.text_shndx && !first_prog) |
2003 | first_prog = prog; | 2056 | first_prog = prog; |
2004 | } | 2057 | } |
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index f85906533cdd..a3a62a583f27 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h | |||
@@ -248,6 +248,14 @@ int bpf_map__pin(struct bpf_map *map, const char *path); | |||
248 | 248 | ||
249 | long libbpf_get_error(const void *ptr); | 249 | long libbpf_get_error(const void *ptr); |
250 | 250 | ||
251 | struct bpf_prog_load_attr { | ||
252 | const char *file; | ||
253 | enum bpf_prog_type prog_type; | ||
254 | enum bpf_attach_type expected_attach_type; | ||
255 | }; | ||
256 | |||
257 | int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, | ||
258 | struct bpf_object **pobj, int *prog_fd); | ||
251 | int bpf_prog_load(const char *file, enum bpf_prog_type type, | 259 | int bpf_prog_load(const char *file, enum bpf_prog_type type, |
252 | struct bpf_object **pobj, int *prog_fd); | 260 | struct bpf_object **pobj, int *prog_fd); |
253 | 261 | ||