mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2026-01-27 06:24:13 +00:00
Reported as:
tc_exec.c: In function ‘do_exec’:
tc_exec.c:103:18: warning: dereference of NULL ‘eu’ [CWE-476] [-Wanalyzer-null-dereference]
103 | return eu->parse_eopt(eu, argc, argv);
| ~~^~~~~~~~~~~~
‘do_exec’: events 1-6
|
| 81 | int do_exec(int argc, char **argv)
| | ^~~~~~~
| | |
| | (1) entry to ‘do_exec’
|......
| 86 | if (argc < 1) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 0’)...
|......
| 91 | if (matches(*argv, "help") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(3) ...to here
| | (4) following ‘true’ branch...
|......
| 96 | strncpy(kind, *argv, sizeof(kind) - 1);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| 97 |
| 98 | eu = get_exec_kind(kind);
| | ~~~~~~~~~~~~~~~~~~~
| | |
| | (6) calling ‘get_exec_kind’ from ‘do_exec’
|
+--> ‘get_exec_kind’: events 7-10
|
| 40 | static struct exec_util *get_exec_kind(const char *name)
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘get_exec_kind’
|......
| 63 | if (eu == NULL)
| | ~
| | |
| | (8) following ‘true’ branch (when ‘eu’ is NULL)...
| 64 | goto noexist;
| | ~~~~
| | |
| | (9) ...to here
|......
| 72 | if (eu) {
| | ~
| | |
| | (10) following ‘false’ branch (when ‘eu’ is NULL)...
|
‘get_exec_kind’: event 11
|
|cc1:
| (11): ...to here
|
<------+
|
‘do_exec’: events 12-13
|
| 98 | eu = get_exec_kind(kind);
| | ^~~~~~~~~~~~~~~~~~~
| | |
| | (12) return of NULL to ‘do_exec’ from ‘get_exec_kind’
|......
| 103 | return eu->parse_eopt(eu, argc, argv);
| | ~~~~~~~~~~~~~~
| | |
| | (13) dereference of NULL ‘eu’
|
Fixes: 4bd624467bc6 ("tc: built-in eBPF exec proxy")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
109 lines
1.9 KiB
C
109 lines
1.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* tc_exec.c "tc exec".
|
|
*
|
|
* Authors: Daniel Borkmann <daniel@iogearbox.net>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <dlfcn.h>
|
|
|
|
#include "utils.h"
|
|
|
|
#include "tc_util.h"
|
|
#include "tc_common.h"
|
|
|
|
static struct exec_util *exec_list;
|
|
static void *BODY;
|
|
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: tc exec [ EXEC_TYPE ] [ help | OPTIONS ]\n"
|
|
"Where:\n"
|
|
"EXEC_TYPE := { bpf | etc. }\n"
|
|
"OPTIONS := ... try tc exec <desired EXEC_KIND> help\n");
|
|
}
|
|
|
|
static int parse_noeopt(struct exec_util *eu, int argc, char **argv)
|
|
{
|
|
if (argc) {
|
|
fprintf(stderr, "Unknown exec \"%s\", hence option \"%s\" is unparsable\n",
|
|
eu->id, *argv);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct exec_util *get_exec_kind(const char *name)
|
|
{
|
|
struct exec_util *eu;
|
|
char buf[256];
|
|
void *dlh;
|
|
|
|
for (eu = exec_list; eu; eu = eu->next)
|
|
if (strcmp(eu->id, name) == 0)
|
|
return eu;
|
|
|
|
snprintf(buf, sizeof(buf), "%s/e_%s.so", get_tc_lib(), name);
|
|
dlh = dlopen(buf, RTLD_LAZY);
|
|
if (dlh == NULL) {
|
|
dlh = BODY;
|
|
if (dlh == NULL) {
|
|
dlh = BODY = dlopen(NULL, RTLD_LAZY);
|
|
if (dlh == NULL)
|
|
goto noexist;
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%s_exec_util", name);
|
|
eu = dlsym(dlh, buf);
|
|
if (eu == NULL)
|
|
goto noexist;
|
|
reg:
|
|
eu->next = exec_list;
|
|
exec_list = eu;
|
|
|
|
return eu;
|
|
noexist:
|
|
eu = calloc(1, sizeof(*eu));
|
|
if (eu) {
|
|
strncpy(eu->id, name, sizeof(eu->id) - 1);
|
|
eu->parse_eopt = parse_noeopt;
|
|
goto reg;
|
|
}
|
|
|
|
return eu;
|
|
}
|
|
|
|
int do_exec(int argc, char **argv)
|
|
{
|
|
struct exec_util *eu;
|
|
char kind[FILTER_NAMESZ] = {};
|
|
|
|
if (argc < 1) {
|
|
fprintf(stderr, "No command given, try \"tc exec help\".\n");
|
|
return -1;
|
|
}
|
|
|
|
if (matches(*argv, "help") == 0) {
|
|
usage();
|
|
return 0;
|
|
}
|
|
|
|
strncpy(kind, *argv, sizeof(kind) - 1);
|
|
|
|
eu = get_exec_kind(kind);
|
|
if (eu == NULL) {
|
|
fprintf(stderr, "Allocation failed finding exec\n");
|
|
return -1;
|
|
}
|
|
|
|
argc--;
|
|
argv++;
|
|
|
|
return eu->parse_eopt(eu, argc, argv);
|
|
}
|