From 14cfba4a80a98063bac40751ed269031fde0891b Mon Sep 17 00:00:00 2001 From: Zsolt Varga Date: Wed, 23 Aug 2023 22:18:47 +0200 Subject: [PATCH] add common context to commands --- Makefile | 6 +++-- commands.c | 36 +++++++++++++++++++++++++ commands.h | 17 ++++++++++++ device_driver.c | 26 +++++++++++++++--- device_driver.h | 3 ++- socket.c | 23 ++++++++++++---- task_context.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ task_context.h | 32 ++++++++++++++++++++++ 8 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 commands.c create mode 100644 commands.h create mode 100644 task_context.c create mode 100644 task_context.h diff --git a/Makefile b/Makefile index 4d6466d4..375059b8 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,9 @@ wasm-objs := third-party/wasm3/source/m3_api_libc.o \ worker_thread.o \ opa.o \ proxywasm.o \ - socket.o + socket.o \ + task_context.o \ + commands.o # Set the path to the Kernel build utils. KBUILD=/lib/modules/$(shell uname -r)/build/ @@ -126,6 +128,6 @@ setup-dev-env: test -f .vscode/c_cpp_properties.json || cp .vscode/c_cpp_properties.json.orig .vscode/c_cpp_properties.json brew tap messense/macos-cross-toolchains brew install $(shell lima uname -m)-unknown-linux-gnu - test -d linux || git clone --depth=1 --branch v6.2 git@github.com:torvalds/linux.git + test -d linux || git clone --depth=1 --branch v6.2 https://github.com/torvalds/linux.git cd linux && lima make tinyconfig cd linux && lima make -j diff --git a/commands.c b/commands.c new file mode 100644 index 00000000..d145af6d --- /dev/null +++ b/commands.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: MIT OR GPL-2.0-only + * + * Licensed under the MIT license or the GPLv2 license + * , at your option. This file may not be copied, + * modified, or distributed except according to those terms. + */ + +#include "device_driver.h" +#include "json.h" + +command_answer *send_accept_command(u16 port) +{ + JSON_Value *root_value = json_value_init_object(); + JSON_Object *root_object = json_value_get_object(root_value); + + json_object_set_number(root_object, "port", port); + + command_answer *answer = send_command("accept", json_serialize_to_string(root_value), get_task_context()); + + return answer; +} + +command_answer *send_connect_command(u16 port) +{ + JSON_Value *root_value = json_value_init_object(); + JSON_Object *root_object = json_value_get_object(root_value); + + json_object_set_number(root_object, "port", port); + + command_answer *answer = send_command("connect", json_serialize_to_string(root_value), get_task_context()); + + return answer; +} diff --git a/commands.h b/commands.h new file mode 100644 index 00000000..3b7e8777 --- /dev/null +++ b/commands.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: MIT OR GPL-2.0-only + * + * Licensed under the MIT license or the GPLv2 license + * , at your option. This file may not be copied, + * modified, or distributed except according to those terms. + */ + +#ifndef commands_h +#define commands_h + +command_answer *send_accept_command(u16 port); +command_answer *send_connect_command(u16 port); + +#endif diff --git a/device_driver.c b/device_driver.c index b46c4e34..fbee73a1 100644 --- a/device_driver.c +++ b/device_driver.c @@ -24,7 +24,7 @@ /* Global variables are declared as static, so are global within the file. */ #define DEFAULT_MODULE_ENTRYPOINT "main" -#define COMMAND_TIMEOUT_SECONDS 5 +#define COMMAND_TIMEOUT_SECONDS 1 static int major; /* major number assigned to our device driver */ @@ -43,6 +43,7 @@ typedef struct command struct list_head list; char *name; char *data; + task_context *context; uuid_t uuid; struct command_answer *answer; wait_queue_head_t wait_queue; @@ -90,13 +91,14 @@ void free_command_answer(struct command_answer *cmd_answer) } // create a function to add a command to the list (called from the VM), locked with a spinlock -command_answer *send_command(char *name, char *data) +command_answer *send_command(char *name, char *data, task_context *context) { struct command *cmd = kmalloc(sizeof(struct command), GFP_KERNEL); uuid_gen(&cmd->uuid); cmd->name = name; cmd->data = data; + cmd->context = context; init_waitqueue_head(&cmd->wait_queue); spin_lock_irqsave(&command_list_lock, command_list_lock_flags); @@ -130,7 +132,12 @@ command_answer *send_command(char *name, char *data) spin_unlock_irqrestore(&command_list_lock, command_list_lock_flags); command_answer *cmd_answer = cmd->answer; + if (cmd->context) + { + free_task_context(cmd->context); + } kfree(cmd); + return cmd_answer; } @@ -164,12 +171,23 @@ static int write_command_to_buffer(char *buffer, size_t buffer_size, struct comm JSON_Value *root_value = json_value_init_object(); JSON_Object *root_object = json_value_get_object(root_value); + if (cmd->context) + { + JSON_Value *context_value = json_value_init_object(); + JSON_Object *context_object = json_value_get_object(context_value); + json_object_set_number(context_object, "uid", cmd->context->uid.val); + json_object_set_number(context_object, "gid", cmd->context->gid.val); + json_object_set_string(context_object, "command_path", cmd->context->command_path); + json_object_set_string(context_object, "command_name", cmd->context->command_name); + json_object_set_value(root_object, "context", context_value); + } + json_object_set_string(root_object, "id", uuid); json_object_set_string(root_object, "command", cmd->name); json_object_set_string(root_object, "data", cmd->data); char *serialized_string = json_serialize_to_string(root_value); - + length = strlen(serialized_string); if (length > buffer_size) { @@ -545,7 +563,7 @@ static ssize_t device_read(struct file *file, /* see include/linux/fs.h */ int json_length = write_command_to_buffer(device_out_buffer, sizeof device_out_buffer, c); if (json_length < 0) - { + { return -EFAULT; } diff --git a/device_driver.h b/device_driver.h index f9944f53..bbf3454f 100644 --- a/device_driver.h +++ b/device_driver.h @@ -15,6 +15,7 @@ #include #include "runtime.h" +#include "task_context.h" static int device_open(struct inode *, struct file *); static int device_release(struct inode *, struct file *); @@ -29,7 +30,7 @@ typedef struct command_answer void free_command_answer(command_answer *cmd_answer); -command_answer *send_command(char *name, char *data); +command_answer *send_command(char *name, char *data, task_context *context); wasm_vm_result load_module(char *name, char *code, unsigned length, char *entrypoint); #define SUCCESS 0 diff --git a/socket.c b/socket.c index a07f7392..88ebfa3a 100644 --- a/socket.c +++ b/socket.c @@ -24,6 +24,7 @@ #include "socket.h" #include "rsa_tools.h" #include "opa.h" +#include "commands.h" #define RSA_OR_EC 0 @@ -906,9 +907,8 @@ struct sock *wasm_accept(struct sock *sk, int flags, int *err, bool kern) proxywasm_unlock(p); - // Sample how to send a command to the userspace agent - const char *data = "{\"port\": \"8000\"}"; - command_answer *answer = send_command("accept", data); + // Sample how to send a command to the userspace agents + command_answer *answer = send_accept_command(port); if (answer->error) { @@ -923,7 +923,7 @@ struct sock *wasm_accept(struct sock *sk, int flags, int *err, bool kern) // We should not only check for empty cert but we must check the certs validity // TODO must set the certificate to avoid new cert generation every time - if (sc->cert->data_len == 0) + if (sc->cert->data_len == 1234) // turn off csr generation for now { // generating certificate signing request if (sc->rsa_priv->plen == 0 || sc->rsa_pub->elen == 0) @@ -1082,9 +1082,22 @@ int wasm_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) proxywasm_unlock(p); + command_answer *answer = send_connect_command(port); + + if (answer->error) + { + pr_err("wasm_accept: failed to send command: %s", answer->error); + } + else + { + pr_info("wasm_accept: command answer: %s", answer->answer); + } + + free_command_answer(answer); + // We should not only check for empty cert but we must check the certs validity // TODO must set the certificate to avoid new cert generation every time - if (sc->cert->data_len == 0) + if (sc->cert->data_len == 1234) // turn off csr generation for now { // generating certificate signing request if (sc->rsa_priv->plen == 0 || sc->rsa_pub->elen == 0) diff --git a/task_context.c b/task_context.c new file mode 100644 index 00000000..15a08519 --- /dev/null +++ b/task_context.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: MIT OR GPL-2.0-only + * + * Licensed under the MIT license or the GPLv2 license + * , at your option. This file may not be copied, + * modified, or distributed except according to those terms. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "task_context.h" + +task_context *get_task_context(void) +{ + struct task_context *context = kmalloc(sizeof(struct task_context), GFP_KERNEL); + + strcpy(context->command_name, current->comm); + context->command_path_buffer = kmalloc(COMMAND_PATH_BUFLEN, GFP_KERNEL); + context->command_path = get_current_proc_path(context->command_path_buffer, COMMAND_PATH_BUFLEN); + current_uid_gid(&context->uid, &context->gid); + + return context; +} + +void free_task_context(struct task_context *context) +{ + if (context->command_path_buffer) + { + kfree(context->command_path_buffer); + } + + kfree(context); +} + +char *get_current_proc_path(char *buf, int buflen) +{ + struct file *exe_file; + char *result = ERR_PTR(-ENOENT); + struct mm_struct *mm; + + mm = get_task_mm(current); + if (!mm) + { + goto out; + } + exe_file = mm->exe_file; + if (exe_file) + { + get_file(exe_file); + path_get(&exe_file->f_path); + } + mmput(mm); + if (exe_file) + { + result = d_path(&exe_file->f_path, buf, buflen); + path_put(&exe_file->f_path); + fput(exe_file); + } + +out: + return result; +} diff --git a/task_context.h b/task_context.h new file mode 100644 index 00000000..a433a812 --- /dev/null +++ b/task_context.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Cisco and/or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: MIT OR GPL-2.0-only + * + * Licensed under the MIT license or the GPLv2 license + * , at your option. This file may not be copied, + * modified, or distributed except according to those terms. + */ + +#ifndef context_h +#define context_h + +#include + +#define COMMAND_PATH_BUFLEN 256 + +char *get_current_proc_path(char *buf, int buflen); + +typedef struct task_context +{ + char command_name[TASK_COMM_LEN]; + char *command_path_buffer; + char *command_path; + kuid_t uid; + kgid_t gid; +} task_context; + +task_context *get_task_context(void); +void free_task_context(struct task_context *context); + +#endif