diff --git a/cve/linux-kernel/2023/CVE-2023-1390/.keep b/cve/linux-kernel/2023/CVE-2023-1390/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cve/linux-kernel/2023/CVE-2023-23003/expr.c b/cve/linux-kernel/2023/CVE-2023-23003/expr.c new file mode 100644 index 0000000000000000000000000000000000000000..0e58955153166af99a1f627d2aab0262aded8e35 --- /dev/null +++ b/cve/linux-kernel/2023/CVE-2023-23003/expr.c @@ -0,0 +1,354 @@ +#include "expr-bison.h" +#include "expr-flex.h" +#include "smt.h" +#include +#include +#include +#include +#include +#ifdef PARSER_DEBUG +extern int expr_debug; +#endif +struct expr_id_data { + union { + struct { + double val; + int source_count; + } val; + struct { + double val; + const char *metric_name; + const char *metric_expr; + } ref; + }; + enum { + /* Holding a double value. */ + EXPR_ID_DATA__VALUE, + /* Reference to another metric. */ + EXPR_ID_DATA__REF, + /* A reference but the value has been computed. */ + EXPR_ID_DATA__REF_VALUE, + } kind; +}; +static size_t key_hash(const void *key, void *ctx __maybe_unused) +{ + const char *str = (const char *)key; + size_t hash = 0; + while (*str != '\0') { + hash *= 31; + hash += *str; + str++; + } + return hash; +} +static bool key_equal(const void *key1, const void *key2, + void *ctx __maybe_unused) +{ + return !strcmp((const char *)key1, (const char *)key2); +} +struct hashmap *ids__new(void) +{ + return hashmap__new(key_hash, key_equal, NULL); +} +void ids__free(struct hashmap *ids) +{ + struct hashmap_entry *cur; + size_t bkt; + if (ids == NULL) + return; + hashmap__for_each_entry(ids, cur, bkt) { + free((char *)cur->key); + free(cur->value); + } + hashmap__free(ids); +} +int ids__insert(struct hashmap *ids, const char *id) +{ + struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + int ret; + ret = hashmap__set(ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); + if (ret) + free(data_ptr); + free(old_key); + free(old_data); + return ret; +} +struct hashmap *ids__union(struct hashmap *ids1, struct hashmap *ids2) +{ + size_t bkt; + struct hashmap_entry *cur; + int ret; + struct expr_id_data *old_data = NULL; + char *old_key = NULL; + if (!ids1) + return ids2; + if (!ids2) + return ids1; + if (hashmap__size(ids1) < hashmap__size(ids2)) { + struct hashmap *tmp = ids1; + ids1 = ids2; + ids2 = tmp; + } + hashmap__for_each_entry(ids2, cur, bkt) { + ret = hashmap__set(ids1, cur->key, cur->value, + (const void **)&old_key, (void **)&old_data); + free(old_key); + free(old_data); + if (ret) { + hashmap__free(ids1); + hashmap__free(ids2); + return NULL; + } + } + hashmap__free(ids2); + return ids1; +} +/* Caller must make sure id is allocated */ +int expr__add_id(struct expr_parse_ctx *ctx, const char *id) +{ + return ids__insert(ctx->ids, id); +} +/* Caller must make sure id is allocated */ +int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) +{ + return expr__add_id_val_source_count(ctx, id, val, /*source_count=*/1); +} +/* Caller must make sure id is allocated */ +int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, + double val, int source_count) +{ + struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + int ret; + data_ptr = malloc(sizeof(*data_ptr)); + if (!data_ptr) + return -ENOMEM; + data_ptr->val.val = val; + data_ptr->val.source_count = source_count; + data_ptr->kind = EXPR_ID_DATA__VALUE; + ret = hashmap__set(ctx->ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); + if (ret) + free(data_ptr); + free(old_key); + free(old_data); + return ret; +} +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) +{ + struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + char *name, *p; + int ret; + data_ptr = zalloc(sizeof(*data_ptr)); + if (!data_ptr) + return -ENOMEM; + name = strdup(ref->metric_name); + if (!name) { + free(data_ptr); + return -ENOMEM; + } + /* + * The jevents tool converts all metric expressions + * to lowercase, including metric references, hence + * we need to add lowercase name for metric, so it's + * properly found. + */ + for (p = name; *p; p++) + *p = tolower(*p); + /* + * Intentionally passing just const char pointers, + * originally from 'struct pmu_event' object. + * We don't need to change them, so there's no + * need to create our own copy. + */ + data_ptr->ref.metric_name = ref->metric_name; + data_ptr->ref.metric_expr = ref->metric_expr; + data_ptr->kind = EXPR_ID_DATA__REF; + ret = hashmap__set(ctx->ids, name, data_ptr, + (const void **)&old_key, (void **)&old_data); + if (ret) + free(data_ptr); + pr_debug2("adding ref metric %s: %s\n", + ref->metric_name, ref->metric_expr); + free(old_key); + free(old_data); + return ret; +} +int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **data) +{ + return hashmap__find(ctx->ids, id, (void **)data) ? 0 : -1; +} +bool expr__subset_of_ids(struct expr_parse_ctx *haystack, + struct expr_parse_ctx *needles) +{ + struct hashmap_entry *cur; + size_t bkt; + struct expr_id_data *data; + hashmap__for_each_entry(needles->ids, cur, bkt) { + if (expr__get_id(haystack, cur->key, &data)) + return false; + } + return true; +} +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **datap) +{ + struct expr_id_data *data; + if (expr__get_id(ctx, id, datap) || !*datap) { + pr_debug("%s not found\n", id); + return -1; + } + data = *datap; + switch (data->kind) { + case EXPR_ID_DATA__VALUE: + pr_debug2("lookup(%s): val %f\n", id, data->val.val); + break; + case EXPR_ID_DATA__REF: + pr_debug2("lookup(%s): ref metric name %s\n", id, + data->ref.metric_name); + pr_debug("processing metric: %s ENTRY\n", id); + data->kind = EXPR_ID_DATA__REF_VALUE; + if (expr__parse(&data->ref.val, ctx, data->ref.metric_expr)) { + pr_debug("%s failed to count\n", id); + return -1; + } + pr_debug("processing metric: %s EXIT: %f\n", id, data->ref.val); + break; + case EXPR_ID_DATA__REF_VALUE: + pr_debug2("lookup(%s): ref val %f metric name %s\n", id, + data->ref.val, data->ref.metric_name); + break; + default: + assert(0); /* Unreachable. */ + } + return 0; +} +void expr__del_id(struct expr_parse_ctx *ctx, const char *id) +{ + struct expr_id_data *old_val = NULL; + char *old_key = NULL; + hashmap__delete(ctx->ids, id, + (const void **)&old_key, (void **)&old_val); + free(old_key); + free(old_val); +} +struct expr_parse_ctx *expr__ctx_new(void) +{ + struct expr_parse_ctx *ctx; + ctx = malloc(sizeof(struct expr_parse_ctx)); + if (!ctx) + return NULL; + + ctx->ids = hashmap__new(key_hash, key_equal, NULL); + if (IS_ERR(ctx->ids)) { + free(ctx); + return NULL; + } + ctx->runtime = 0; + + return ctx; +} +void expr__ctx_clear(struct expr_parse_ctx *ctx) +{ + struct hashmap_entry *cur; + size_t bkt; + hashmap__for_each_entry(ctx->ids, cur, bkt) { + free((char *)cur->key); + free(cur->value); + } + hashmap__clear(ctx->ids); +} +void expr__ctx_free(struct expr_parse_ctx *ctx) +{ + struct hashmap_entry *cur; + size_t bkt; + hashmap__for_each_entry(ctx->ids, cur, bkt) { + free((char *)cur->key); + free(cur->value); + } + hashmap__free(ctx->ids); + free(ctx); +} +static int +__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + bool compute_ids) +{ + struct expr_scanner_ctx scanner_ctx = { + .runtime = ctx->runtime, + }; + YY_BUFFER_STATE buffer; + void *scanner; + int ret; + pr_debug2("parsing metric: %s\n", expr); + ret = expr_lex_init_extra(&scanner_ctx, &scanner); + if (ret) + return ret; + buffer = expr__scan_string(expr, scanner); +#ifdef PARSER_DEBUG + expr_debug = 1; + expr_set_debug(1, scanner); +#endif + ret = expr_parse(val, ctx, compute_ids, scanner); + expr__flush_buffer(buffer, scanner); + expr__delete_buffer(buffer, scanner); + expr_lex_destroy(scanner); + return ret; +} +int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr) +{ + return __expr__parse(final_val, ctx, expr, /*compute_ids=*/false) ? -1 : 0; +} +int expr__find_ids(const char *expr, const char *one, + struct expr_parse_ctx *ctx) +{ + int ret = __expr__parse(NULL, ctx, expr, /*compute_ids=*/true); + if (one) + expr__del_id(ctx, one); + return ret; +} +double expr_id_data__value(const struct expr_id_data *data) +{ + if (data->kind == EXPR_ID_DATA__VALUE) + return data->val.val; + assert(data->kind == EXPR_ID_DATA__REF_VALUE); + return data->ref.val; +} +double expr_id_data__source_count(const struct expr_id_data *data) +{ + assert(data->kind == EXPR_ID_DATA__VALUE); + return data->val.source_count; +} +double expr__get_literal(const char *literal) +{ + static struct cpu_topology *topology; + if (!strcmp("#smt_on", literal)) + return smt_on() > 0 ? 1.0 : 0.0; + if (!strcmp("#num_cpus", literal)) + return cpu__max_present_cpu(); + /* + * Assume that topology strings are consistent, such as CPUs "0-1" + * wouldn't be listed as "0,1", and so after deduplication the number of + * these strings gives an indication of the number of packages, dies, + * etc. + */ + if (!topology) { + topology = cpu_topology__new(); + if (!topology) { + pr_err("Error creating CPU topology"); + return NAN; + } + } + if (!strcmp("#num_packages", literal)) + return topology->package_cpus_lists; + if (!strcmp("#num_dies", literal)) + return topology->die_cpus_lists; + if (!strcmp("#num_cores", literal)) + return topology->core_cpus_lists; + pr_err("Unrecognized literal '%s'", literal); + return NAN; +} \ No newline at end of file diff --git a/cve/linux-kernel/2023/yaml/CVE-2023-1390.yaml b/cve/linux-kernel/2023/yaml/CVE-2023-1390.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5443c83e457f2c1eda1cf05d67bed3f31a67b1e6 --- /dev/null +++ b/cve/linux-kernel/2023/yaml/CVE-2023-1390.yaml @@ -0,0 +1,18 @@ +id: CVE-2023-1390 +source: https://www.opencve.io/cve/CVE-2023-1390 +info: + name: 一个在Linux 内核的 TIPC 内核模块中发现远程拒绝服务漏洞。 + severity: Medium + description:tipc_link_xmit() 中的 while 循环在尝试解析不在队列中的 SKB 时遇到未知状态。向具有 UDP 承载的系统发送两个小 UDP 数据包会导致系统的 CPU 利用率立即飙升至 100%,从而导致拒绝服务情况。 + scope-of-influence: + 5.5~5.15 + reference: + -https://github.com/torvalds/linux/commit/b77413446408fdd256599daf00d5be72b5f3e7c6 + -https://gist.github.com/netspooky/bee2d07022f6350bb88eaa48e571d9b5 + -https://infosec.exchange/@_mattata/109427999461122360 + classification: + cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H + cvss-score: + cve-id: CVE-2023-1390 + cwe-id: + tags: TIPC,拒绝服务攻击 \ No newline at end of file diff --git a/cve/linux-kernel/2023/yaml/CVE-2023-23003.yaml b/cve/linux-kernel/2023/yaml/CVE-2023-23003.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e02af285eb2e6bb8508a0650f024ea4f72e0018f --- /dev/null +++ b/cve/linux-kernel/2023/yaml/CVE-2023-23003.yaml @@ -0,0 +1,19 @@ +id: CVE-2023-23003 +source: Linux kernel prior to 5.16 +info: + name: Linux kernel perf工具expr.c空指针解引用漏洞 + severity: 高危 + description: Linux kernel中的perf工具是一种性能测试和调优工具,可以使用它来测量各种系统性能。Linux内核版本5.16之前的perf工具中存在漏洞。由于缺乏对hashmap__new返回值的检查,攻击者可以利用该漏洞来导致空指针解引用和拒绝服务攻击。成功利用此漏洞需要攻击者在系统上拥有一定的权限。 + scope-of-influence: Linux kernel版本5.16之前的perf工具。 + reference: + - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23003 + - https://nvd.nist.gov/vuln/detail/CVE-2023-23003 + - https://nvd.nist.gov/vuln/detail/CVE-2023-23003 + - https://github.com/torvalds/linux/commit/0a515a06c5ebfa46fee3ac519e418f801e718da4 + classification: + cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H + cvss-score:7.8 + cve-id: CVE-2023-23003 + cwe-id:CWE-252 + tags: NULL Pointer Dereference, perf, Linux kernel, denial-of-service + \ No newline at end of file diff --git a/openkylin_list.yaml b/openkylin_list.yaml index cae1e168f77fb28a2363540f49132effef2a42d6..23a4837b5ec51c1fc95c113fd1045ece1f110743 100644 --- a/openkylin_list.yaml +++ b/openkylin_list.yaml @@ -58,7 +58,7 @@ cve: - CVE-2022-25265 - CVE-2022-41218 - CVE-2019-13272 - - CVE-2020-12351 + - CVE-2023-23003 sudo: - CVE-2021-3156 - CVE-2023-22809