// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2024 Samsung Electronics Co., Ltd * http://www.samsung.com * */ #include #include #include #include #include #include #include #include #include #include #include #include "kzt_main.h" #include "kzt_common.h" static int __kzt_offset_task_struct_offsets(u32 *offsets); static int __kzt_offset_cred_offsets(u32 *offsets); static int __kzt_offset_fs_struct_offsets(u32 *offsets); static int __kzt_offset_mm_struct_offsets(u32 *offsets); static int __kzt_offset_file_offsets(u32 *offsets); static int __kzt_offset_path_offsets(u32 *offsets); static int __kzt_offset_dentry_offsets(u32 *offsets); static int __kzt_offset_qstr_offsets(u32 *offsets); static int __kzt_offset_inode_offsets(u32 *offsets); static int __kzt_offset_timespec64_offsets(u32 *offsets); static int __kzt_offset_sock_offsets(u32 *offsets); static int kzt_offset_task_struct_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_task_struct_offsets(arg->task_struct_.offsets); if (!err) arg->version = VERSION_OF_TASK_STRUCT_INTERESTS; return err; } static int __kzt_offset_task_struct_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[MM_OF_TASK_STRUCT] = offsetof(struct task_struct, mm); if (offsets[MM_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[EXIT_CODE_OF_TASK_STRUCT] = offsetof(struct task_struct, exit_code); if (offsets[EXIT_CODE_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[PID_OF_TASK_STRUCT] = offsetof(struct task_struct, pid); if (offsets[PID_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[TGID_OF_TASK_STRUCT] = offsetof(struct task_struct, tgid); if (offsets[TGID_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[REAL_PARENT_OF_TASK_STRUCT] = offsetof(struct task_struct, real_parent); if (offsets[REAL_PARENT_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[UTIME_OF_TASK_STRUCT] = offsetof(struct task_struct, utime); if (offsets[UTIME_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[STIME_OF_TASK_STRUCT] = offsetof(struct task_struct, stime); if (offsets[STIME_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[START_TIME_OF_TASK_STRUCT] = offsetof(struct task_struct, start_time); if (offsets[START_TIME_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[CRED_OF_TASK_STRUCT] = offsetof(struct task_struct, cred); if (offsets[CRED_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; offsets[FS_OF_TASK_STRUCT] = offsetof(struct task_struct, fs); if (offsets[FS_OF_TASK_STRUCT] >= sizeof(struct task_struct)) break; } while ((err = 0)); return err; } static int kzt_offset_cred_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_cred_offsets(arg->cred_.offsets); if (!err) arg->version = VERSION_OF_CRED_INTERESTS; return err; } static int __kzt_offset_cred_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[UID_OF_CRED] = offsetof(struct cred, uid); if (offsets[UID_OF_CRED] >= sizeof(struct cred)) break; offsets[GID_OF_CRED] = offsetof(struct cred, gid); if (offsets[GID_OF_CRED] >= sizeof(struct cred)) break; offsets[SUID_OF_CRED] = offsetof(struct cred, suid); if (offsets[SUID_OF_CRED] >= sizeof(struct cred)) break; offsets[SGID_OF_CRED] = offsetof(struct cred, sgid); if (offsets[SGID_OF_CRED] >= sizeof(struct cred)) break; offsets[EUID_OF_CRED] = offsetof(struct cred, euid); if (offsets[EUID_OF_CRED] >= sizeof(struct cred)) break; offsets[EGID_OF_CRED] = offsetof(struct cred, egid); if (offsets[EGID_OF_CRED] >= sizeof(struct cred)) break; offsets[FSUID_OF_CRED] = offsetof(struct cred, fsuid); if (offsets[FSUID_OF_CRED] >= sizeof(struct cred)) break; offsets[FSGID_OF_CRED] = offsetof(struct cred, fsgid); if (offsets[FSGID_OF_CRED] >= sizeof(struct cred)) break; } while ((err = 0)); return err; } static int kzt_offset_fs_struct_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_fs_struct_offsets(arg->fs_struct_.offsets); if (!err) arg->version = VERSION_OF_FS_STRUCT_INTERESTS; return err; } static int __kzt_offset_fs_struct_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[PWD_OF_FS_STRUCT] = offsetof(struct fs_struct, pwd); if (offsets[PWD_OF_FS_STRUCT] >= sizeof(struct fs_struct)) break; } while ((err = 0)); return err; } static int kzt_offset_mm_struct_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_mm_struct_offsets(arg->mm_struct_.offsets); if (!err) arg->version = VERSION_OF_MM_STRUCT_INTERESTS; return err; } static int __kzt_offset_mm_struct_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[EXE_FILE_OF_MM_STRUCT] = offsetof(struct mm_struct, exe_file); if (offsets[EXE_FILE_OF_MM_STRUCT] >= sizeof(struct mm_struct)) break; } while ((err = 0)); return err; } static int kzt_offset_file_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_file_offsets(arg->file_.offsets); if (!err) arg->version = VERSION_OF_FILE_INTERESTS; return err; } static int __kzt_offset_file_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[F_PATH_OF_FILE] = offsetof(struct file, f_path); if (offsets[F_PATH_OF_FILE] >= sizeof(struct file)) break; } while ((err = 0)); return err; } static int kzt_offset_path_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_path_offsets(arg->path_.offsets); if (!err) arg->version = VERSION_OF_PATH_INTERESTS; return err; } static int __kzt_offset_path_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[DENTRY_OF_PATH] = offsetof(struct path, dentry); if (offsets[DENTRY_OF_PATH] >= sizeof(struct path)) break; } while ((err = 0)); return err; } static int kzt_offset_dentry_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_dentry_offsets(arg->dentry_.offsets); if (!err) arg->version = VERSION_OF_DENTRY_INTERESTS; return err; } static int __kzt_offset_dentry_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[D_PARENT_OF_DENTRY] = offsetof(struct dentry, d_parent); if (offsets[D_PARENT_OF_DENTRY] >= sizeof(struct dentry)) break; offsets[D_NAME_OF_DENTRY] = offsetof(struct dentry, d_name); if (offsets[D_NAME_OF_DENTRY] >= sizeof(struct dentry)) break; offsets[D_INODE_OF_DENTRY] = offsetof(struct dentry, d_inode); if (offsets[D_INODE_OF_DENTRY] >= sizeof(struct dentry)) break; } while ((err = 0)); return err; } static int kzt_offset_qstr_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_qstr_offsets(arg->qstr_.offsets); if (!err) arg->version = VERSION_OF_QSTR_INTERESTS; return err; } static int __kzt_offset_qstr_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[NAME_OF_QSTR] = offsetof(struct qstr, name); if (offsets[NAME_OF_QSTR] >= sizeof(struct qstr)) break; } while ((err = 0)); return err; } static int kzt_offset_inode_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_inode_offsets(arg->inode_.offsets); if (!err) arg->version = VERSION_OF_INODE_INTERESTS; return err; } static int __kzt_offset_inode_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[I_MODE_OF_INODE] = offsetof(struct inode, i_mode); if (offsets[I_MODE_OF_INODE] >= sizeof(struct inode)) break; offsets[I_UID_OF_INODE] = offsetof(struct inode, i_uid); if (offsets[I_UID_OF_INODE] >= sizeof(struct inode)) break; offsets[I_GID_OF_INODE] = offsetof(struct inode, i_gid); if (offsets[I_GID_OF_INODE] >= sizeof(struct inode)) break; offsets[I_INO_OF_INODE] = offsetof(struct inode, i_ino); if (offsets[I_INO_OF_INODE] >= sizeof(struct inode)) break; offsets[I_ATIME_OF_INODE] = offsetof(struct inode, i_atime); if (offsets[I_ATIME_OF_INODE] >= sizeof(struct inode)) break; offsets[I_MTIME_OF_INODE] = offsetof(struct inode, i_mtime); if (offsets[I_MTIME_OF_INODE] >= sizeof(struct inode)) break; offsets[I_CTIME_OF_INODE] = offsetof(struct inode, __i_ctime); if (offsets[I_CTIME_OF_INODE] >= sizeof(struct inode)) break; } while ((err = 0)); return err; } static int kzt_offset_timespec64_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_timespec64_offsets(arg->timespec64_.offsets); if (!err) arg->version = VERSION_OF_TIMESPEC64_INTERESTS; return err; } static int __kzt_offset_timespec64_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[TV_SEC_OF_TIMESPEC64] = offsetof(struct timespec64, tv_sec); if (offsets[TV_SEC_OF_TIMESPEC64] >= sizeof(struct timespec64)) break; } while ((err = 0)); return err; } static int kzt_offset_sock_offsets(struct kzt_get_offsets_arg *arg) { int err = __kzt_offset_sock_offsets(arg->sock_.offsets); if (!err) arg->version = VERSION_OF_SOCK_INTERESTS; return err; } static int __kzt_offset_sock_offsets(u32 *offsets) { int err = -EFAULT; do { offsets[SK_TYPE_OF_SOCK] = offsetof(struct sock, sk_type); if (offsets[SK_TYPE_OF_SOCK] >= sizeof(struct sock)) break; offsets[SK_UID_OF_SOCK] = offsetof(struct sock, sk_uid); if (offsets[SK_UID_OF_SOCK] >= sizeof(struct sock)) break; } while ((err = 0)); return err; } int kzt_offset_get_offsets(struct kzt_get_offsets_arg *arg) { switch (arg->type) { case STRUCT_TYPE_TASK_STRUCT: return kzt_offset_task_struct_offsets(arg); case STRUCT_TYPE_CRED: return kzt_offset_cred_offsets(arg); case STRUCT_TYPE_FS_STRUCT: return kzt_offset_fs_struct_offsets(arg); case STRUCT_TYPE_MM_STRUCT: return kzt_offset_mm_struct_offsets(arg); case STRUCT_TYPE_FILE: return kzt_offset_file_offsets(arg); case STRUCT_TYPE_PATH: return kzt_offset_path_offsets(arg); case STRUCT_TYPE_DENTRY: return kzt_offset_dentry_offsets(arg); case STRUCT_TYPE_QSTR: return kzt_offset_qstr_offsets(arg); case STRUCT_TYPE_INODE: return kzt_offset_inode_offsets(arg); case STRUCT_TYPE_TIMESPEC64: return kzt_offset_timespec64_offsets(arg); case STRUCT_TYPE_SOCK: return kzt_offset_sock_offsets(arg); case STRUCT_TYPE_NONE: case STRUCT_TYPE_NONE_END: return -EPERM; } }