shell bypass 403
/** @file transport_protocol.h @brief SI-based protocol @details Copyright (c) 2024 Acronis International GmbH @author Denis Kopyrin ([email protected]) @since $Id: $ */ #pragma once // Note: This file is shared between kernel and user space transport code. #ifndef BPF_PROGRAM #define KERNEL_READ(p, m) ((p)->m) #define KERNEL_READ2(p, m1, m2) ((p)->m1->m2) // Note: Linux kernel build system defines '__KERNEL__' #if defined __KERNEL__ #include <linux/types.h> // bool, [u]int(8|16|32|64)_t, pid_t #else #include <stdbool.h> // bool #include <stdint.h> // [u]int(8|16|32|64)_t #include <sys/types.h> // pid_t #endif #endif #if !defined PACKED #define PACKED __attribute__((packed)) #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define TRANSPORT_DEVICE_NAME "apl_transport" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Each message is either a 'query' or a 'reply'. Each message contains an identifier ('id') necessary to match 'reply' to corresponding 'query'. Zero 'id' in 'query' means that 'reply' is not necessary. 'reply' with zero 'id' is not used. */ typedef uint64_t msg_id_t; typedef enum { // reserved 0 as an error type AT_PING = 1, // 8 was reserved but now used for 'AT_GET_VERSION' // as it would behave fine - it was not used by ioctl or write AT_GET_VERSION = 8, AT_OPEN_FILE_FROM_MSG, AT_OPEN_FILE_BY_PATH, // 11 and 12 are reserved AT_INIT_SHARED_DATA_QUEUE = 13, AT_WAIT_SHARED_DATA_QUEUE, // 15 is reserved AT_FILE_CONTEXT_ADD = 16, AT_GET_MNT_ID_OFFSET, AT_SET_LISTENING_MASK_GLOBAL, AT_SET_LISTENING_MASK_PROCESS, AT_GET_PROCESS_INFO, AT_GET_PROCESS_PID_VERSION, // Provides mask of events that will be sent if subtype mask intersects // Default is all bits enabled. AT_SET_LISTENING_SUBTYPE_INCLUSION_MASK, // Providers mask of events that will be dropped if subtypes mask intersects. // Default is all bits disabled. AT_SET_LISTENING_SUBTYPE_EXCLUSION_MASK, AT_SET_TRANSPORT_CLIENT_TYPE, AT_LAST, } action_type_t; typedef enum { RT_ERROR = 0, // reserved till 8 RT_OPENED_FILE = 9, RT_VERSION_INFO, RT_DATA_QUEUE_OFFSETS, RT_GET_MNT_ID_OFFSET, RT_GET_PROCESS_INFO, RT_GET_PROCESS_PID_VERSION, } return_type_t; typedef uint8_t msg_type_img_t; typedef struct PACKED { msg_id_t id; msg_type_img_t type; // msg_type_t bool reply; uint8_t payload[]; } request_msg_img_t; inline static msg_id_t msg_img_id(const request_msg_img_t *msg_img) { return msg_img->id; } inline static msg_type_img_t msg_img_type(const request_msg_img_t *msg_img) { return msg_img->type; } inline static bool msg_img_is_reply(const request_msg_img_t *msg_img) { return msg_img->reply; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Generic 'reply' message */ // Note: Empty 'reply' may be used as shortcut for 'default' reply /* // Legacy 'reply_img_t' typedef struct PACKED { uint8_t reply[]; } reply_img_t; */ typedef enum { RT_ALLOW, RT_BLOCK, } reply_type_t; typedef uint8_t reply_type_img_t; typedef struct PACKED { reply_type_img_t type; uint8_t payload[]; } reply_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* 'transport' testing 'pong' message is 'high level' reply to 'ping' message. 'pong' message returns 'payload' from 'ping' message. 'ping' and 'pong' messages can be sent in both 'synchronous' (i.e with *_reply') and 'asynchronous' (i.e without *_reply') modes. 'ping_reply' and 'pong_reply' are respective 'low level' confirmations for 'ping' and 'pong' messages. They do not return 'payload'. Instead they return some arbitrary 'reply'. 'ping' will set 'properties_number' and copy 'payload' as is, it is up to sender to interpret 'payload' correctly. */ typedef struct PACKED { uint64_t process_uid; uint32_t properties_number; uint8_t payload[]; } ping_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* task_info_map management */ typedef uint32_t pid_img_t; typedef uint32_t uid_img_t; typedef uint32_t gid_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // AT_OPEN_FILE_FROM_MSG typedef struct PACKED { // useful for 'rename*' message that may refer to 2 files int num; } open_file_from_msg_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // AT_OPEN_FILE_BY_PATH typedef struct PACKED { int flags; int mode; char path[]; } open_file_by_path_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // RT_OPENED_FILE typedef struct PACKED { int fd; } opened_file_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // AT_SET_LISTENING_MASK_PROCESS typedef struct PACKED { pid_img_t pid; // You may provide pid_version==0 or unique_pid==0 to avoid checking those // but it is unlikely that it is what you actually need. // If unique_pid==0, a different process on pid wrapping might be filtered, // if pid_version==0, a different process exec instance might be filtered. uint64_t pid_version; uint64_t unique_pid; uint64_t events_mask; } process_set_listening_mask_img_t; // Complex events are events that are made from pre and post events together. // It is very common that on LSM there is full information about the file path // but on POST event there is only 'inode' which does not provide full path or mount. // Userspace combines those 2 events to create a POST full event using 'replay cache'. // Driver is capable of sending 'CLOSE' events #define DRIVER_FEATURE_CLOSE_EVENT (1 << 0) // Driver is using AUDIT events to generate Login/Logout events #define DRIVER_FEATURE_AUDIT_EVENTS (1 << 1) // Driver is using 'fsnotify' to send 'POST' events #define DRIVER_FEATURE_FSNOTIFY_EVENTS (1 << 2) // Driver is using LSM 'struct path' to instantiate OPEN events instead of syscall hooks // This also means that driver is sending 'FSNOTIFY_CREATE' events for complex 'CREATE'. // It is not explicitly specified how 'inode' 'CREATE' is done - it can be done via 'fsnotify' or LSM 'inode_create'. // A usual flow is getting 'inode' CREATE event and enriching it with 'path' from LSM 'file_open' event. // This flag requires 'DRIVER_FEATURE_FSNOTIFY_EVENTS' to be set. #define DRIVER_FEATURE_LSM_FILE_OPEN_COMPLEX_CREATE (1 << 3) // Driver is using LSM with CONFIG_SECURITY_PATH to instantiate non-OPEN complex events // instead of syscall hooks that are replayed using 'fsnotify' callbacks. // There are currently 2 events that fall in this category - 'rename' and 'unlink/rmdir'. // They needed to ensure those operations did succeed for POST callbacks. // Userspace client is expected to handle PRE LSM events and verify it using POST 'fsnotify'. // This flag requires 'DRIVER_FEATURE_FSNOTIFY_EVENTS' and 'DRIVER_FEATURE_LSM_GENERIC' to be set. #define DRIVER_FEATURE_LSM_SECURITY_PATH_COMPLEX_POST (1 << 4) // Driver is leveraging proc_connector hooks to have sleepable process events. // This allows to have a more stable process events and required from 'cmdline' in EXEC events. #define DRIVER_FEATURE_SLEEPABLE_PROCESS_EVENTS (1 << 5) // Driver is using syscall hooks instead of LSM for events that requires complex POST. // Such events are currently 'rename' and 'unlink/rmdir'. // Should not be set with 'DRIVER_FEATURE_LSM_SECURITY_PATH_COMPLEX_POST' #define DRIVER_FEATURE_FS_SYSCALL_HOOKS_COMPLEX_POST (1 << 6) // Driver is using LSM to generate generic events like 'settime' that do not require 'CONFIG_SECURITY_PATH' #define DRIVER_FEATURE_LSM_GENERIC (1 << 7) // Driver is using LSM with CONFIG_SECURITY_PATH to instantiate events that do not require 'fsnotify' // For example those events are 'truncate', 'link',... // This flag requires 'DRIVER_FEATURE_LSM_GENERIC' to be set. #define DRIVER_FEATURE_LSM_SECURITY_PATH_SIMPLE_PRE (1 << 8) // Driver is providing 'mmap' events using LSM. // This flag requires 'DRIVER_FEATURE_LSM_GENERIC' to be set. #define DRIVER_FEATURE_LSM_FILE_MMAP (1 << 9) // Driver can provide command line for EXEC events. #define DRIVER_FEATURE_COMMAND_LINE_IN_EXEC (1 << 10) // Driver provides proper absolute paths in events without chroot #define DRIVER_FEATURE_ABSOLUTE_PATHS (1 << 11) // Driver is using 'rw_verify_area' to send read/write events #define DRIVER_FEATURE_RW_VERIFY_AREA_EVENTS (1 << 12) // Driver is using LSM to send network events. // This flag requires 'DRIVER_FEATURE_LSM_GENERIC' to be set. #define DRIVER_FEATURE_LSM_NETWORK (1 << 13) // Driver is capable of using kretprobe hooks #define DRIVER_FEATURE_KRETPROBE_HOOKS (1 << 14) // Driver can handle process failed lookups #define DRIVER_FEATURE_FAILED_LOOKUP (1 << 15) // Driver sends OS accelerated copy file events for 'sendfile' #define DRIVER_FEATURE_COPYFILE_SPLICE (1 << 16) // Driver sends OS accelerated copy file events for 'copy_file_range' #define DRIVER_FEATURE_COPYFILE_COPY_FILE_RANGE (1 << 17) // Driver sends OS accelerated copy file events for 'FICLONE' #define DRIVER_FEATURE_COPYFILE_CLONE (1 << 18) // RT_VERSION_INFO typedef struct PACKED { // Max Action allowed to be called in 'ioctl'/'write' calls // If AT_GET_VERSION errors out itself, 'max_action' should be AT_GET_VERSION uint8_t max_action; // Features exposed by the module that are outside of 'ioctl'/'write' scope uint64_t features; } version_info_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define MSG_TYPE_TO_EVENT_MASK(mt) (1ULL << (mt)) // AT_SET_LISTENING_MASK_GLOBAL // AT_SET_LISTENING_SUBTYPE_INCLUSION_MASK // AT_SET_LISTENING_SUBTYPE_EXCLUSION_MASK typedef struct PACKED { // Mask of events as per 'LEGACY_MSG_TYPE_TO_EVENT_MASK' or per 'MSG_TYPE_TO_EVENT_MASK' uint64_t events_mask; } events_mask_img_t; typedef struct PACKED { int mntId; int fd; } mnt_info_t; // AT_GET_MNT_ID_OFFSET typedef struct PACKED { uint32_t count; char data[]; } mnt_info_img_t; // RT_GET_MNT_ID_OFFSET typedef struct PACKED { bool ok; } mnt_info_ret_img_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - typedef uint64_t offset_img_t; // Note: 'loff_t' is 'signed' typedef uint64_t size_img_t; // Technically 'file_key_t' is not used in transport but it is oftentimes represented the same way // in userspace and kernel space. So it is defined here for convenience. typedef struct { uint64_t ptr; uint64_t ino; uint64_t gen; uint64_t dev; } file_key_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - typedef enum { IOCTL_READ_MSG = 1, IOCTL_WRITE_MSG = 2, IOCTL_WRITE_AND_READ_MSG = 3, IOCTL_READ_VERSION = 4, } ioctl_cmd_t; typedef uint16_t ioctl_size_img_t; typedef struct PACKED { ioctl_size_img_t capacity; // payload capacity; ioctl_size_img_t size; // actual payload size; uint8_t payload[]; } ioctl_hdr_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Shared Data queue protocol // Entry description in the mmap'd buffer // !!! This structure should be exactly the same as 'SiEvent' start !!! typedef struct { uint32_t size; uint8_t data[]; } data_queue_entry_t; // Params passed to the data_queue init // AT_INIT_SHARED_DATA_QUEUE typedef struct PACKED { uint32_t size; } data_queue_params_t; // Those offsets correspond to values in the 'mmap' buffer // /* struct shared_data_queue { uint32_t size ____cacheline_aligned_in_smp; uint32_t head ____cacheline_aligned_in_smp; uint32_t tail ____cacheline_aligned_in_smp; struct data_queue_entry entries[] ____cacheline_aligned_in_smp; }; */ // RT_DATA_QUEUE_OFFSETS typedef struct { uint32_t size; // as size of the whole 'queue' uint32_t headOff; uint32_t tailOff; uint32_t entriesOff; } data_queue_offsets_t; typedef struct PACKED { pid_img_t pid; // pid_t } get_pid_info_img_t; typedef get_pid_info_img_t get_process_info_img_t; typedef get_pid_info_img_t get_process_pid_version_img_t; // RT_GET_PROCESS_PID_VERSION // Returns 'generated' fields for the process from task info map typedef struct PACKED { uint64_t pid_version; uint64_t artificial_process_start_timestamp; } process_pid_version_ret_img_t; // AT_SET_TRANSPORT_CLIENT_TYPE typedef enum { CLIENT_UNKNOWN, CLIENT_TEST, CLIENT_AP, CLIENT_RTP, CLIENT_BE, } client_type_t; #define TRANSPORT_MAX_NAME_LEN 16 typedef struct PACKED { uint8_t client_type; // client_type_t } transport_client_type_img_t; // New events are like SiEvent // Will need to be 'recoded' to public SiEvent if necessary typedef enum { #define FP_SI_MSG_TYPE(x) FP_SI_OT_##x, #include "transport_message_types_x.h" #undef FP_SI_MSG_TYPE } msg_type_t; typedef enum { // open is opening file to modify it. Usually it is WRITE but it can be O_TRUNC as well FP_SI_ST_SYNC_OPEN_MODIFY, // open has read permission // event will be risen only if either 'MODIFY' or 'OPEN' is on, O_PATH case is not sent FP_SI_ST_SYNC_OPEN_READ, // O_CREAT is on FP_SI_ST_SYNC_OPEN_MAY_CREATE, FP_SI_ST_NOTIFY_OPEN_MODIFY, FP_SI_ST_NOTIFY_OPEN_READ, FP_SI_ST_NOTIFY_OPEN_MAY_CREATE, // fsnotify only provides enough if file was opened with WRITE permissions so // the best distinguising factor here is WRITE or !WRITE FP_SI_ST_SYNC_CLOSE_WRITE, FP_SI_ST_SYNC_CLOSE_NON_WRITE, FP_SI_ST_NOTIFY_CLOSE_WRITE, FP_SI_ST_NOTIFY_CLOSE_NON_WRITE, // mmap WRITE is set only when mapping can writeback data to file FP_SI_ST_SYNC_MMAP_WRITE, FP_SI_ST_SYNC_MMAP_NON_WRITE, FP_SI_ST_NOTIFY_MMAP_WRITE, FP_SI_ST_NOTIFY_MMAP_NON_WRITE, // open is related to 'opendir' call FP_SI_ST_NOTIFY_OPENDIR, FP_SI_ST_SYNC_OPENDIR, // close is related to 'closedir' call FP_SI_ST_NOTIFY_CLOSEDIR, FP_SI_ST_SYNC_CLOSEDIR, // flag that is set for all 'special' files operations - !regular && !dir FP_SI_ST_SPECIAL, FP_SI_ST_COUNT, } msg_subtype_t; typedef enum { SI_PI_PRIVATE_PROPERTY_START = 0x4000, SI_PI_PRIVATE_FSUID, SI_PI_PRIVATE_FSGID, SI_PI_PRIVATE_PARENT_THREAD_ID, SI_PI_PRIVATE_OBJECT_FILE_GENERATION, SI_PI_PRIVATE_TARGET_FILE_GENERATION, SI_PI_PRIVATE_OBJECT_FILE_PTR, SI_PI_PRIVATE_TARGET_FILE_PTR, SI_PI_PRIVATE_OBJECT_FILE_MOUNT_ID, SI_PI_PRIVATE_TARGET_FILE_MOUNT_ID, SI_PI_PRIVATE_SEQUENCE_NUMBER, SI_PI_PRIVATE_TARGET_FILE_HANDLE, SI_PI_PRIVATE_TARGET_EXISTS, SI_PI_PRIVATE_OTHER_THREAD_ID, SI_PI_PRIVATE_OTHER_PROCESS_ID, SI_PI_PRIVATE_OTHER_PROCESS_ID_VERSION, SI_PI_PRIVATE_PARENT_PROCESS_ID_VERSION, SI_PI_PRIVATE_OTHER_ARTIFICIAL_PROCESS_START_TIMESTAMP, SI_PI_PRIVATE_FILE_MODE, SI_PI_PRIVATE_FILE_SIZE, SI_PI_PRIVATE_FILE_UID, SI_PI_PRIVATE_FILE_GID, SI_PI_PRIVATE_TARGET_FILE_ATTRIBUTES, SI_PI_PRIVATE_TARGET_FILE_MODE, SI_PI_PRIVATE_TARGET_FILE_SIZE, SI_PI_PRIVATE_TARGET_FILE_UID, SI_PI_PRIVATE_TARGET_FILE_GID, SI_PI_PRIVATE_TARGET_FILE_MODIFICATION_TIME, SI_PI_PRIVATE_TARGET_FILE_CHANGE_TIME, SI_PI_PRIVATE_TARGET_FILE_ACCESS_TIME, SI_PI_PRIVATE_VOLUME_MAGIC, SI_PI_PRIVATE_COMMAND_LINE_TRUNCATED, SI_PI_PRIVATE_OTHER_PROCESS_START_TIMESTAMP, SI_PI_PRIVATE_TARGET_FILE_BIRTH_TIME, SI_PI_PRIVATE_SOCKET_ADDRESS_IP, SI_PI_PRIVATE_LOG_STR, SI_PI_PRIVATE_SOCKET_LOCAL_ADDRESS_IP, SI_PI_PRIVATE_OBJECT_FILE_DENTRY_PTR, SI_PI_PRIVATE_OBJECT_FILE_DENTRY_NAME_PTR, FP_SI_PI_MAX_PRIVATE_PROPERTY_ID, } si_private_property_id_t; #define FP_SI_CT_WANT_REPLY 0xffff