/** @file path_tools.h @brief Tools for working with 'struct path' @details Copyright (c) 2024 Acronis International GmbH @author Bruce Wang ([email protected]) @since $Id: $ */ #pragma once #include "file_contexts.h" #include "file_key_tools.h" #include <linux/fcntl.h> #include <linux/magic.h> static inline bool make_file_context_info(file_context_info_t *info , const struct path *path , int flags , uint64_t low, uint64_t high , uint64_t pid_version) { if (!path || !path->dentry || !path->dentry->d_inode) { return false; } make_key_from_inode(&info->msg_info.key.file_key, path->dentry->d_inode); #ifdef HAVE_INODE_GET_MTIME info->msg_info.key.i_mtime.tv_sec = inode_get_mtime(path->dentry->d_inode).tv_sec; info->msg_info.key.i_mtime.tv_nsec = inode_get_mtime(path->dentry->d_inode).tv_nsec; #else info->msg_info.key.i_mtime.tv_sec = path->dentry->d_inode->i_mtime.tv_sec; info->msg_info.key.i_mtime.tv_nsec = path->dentry->d_inode->i_mtime.tv_nsec; #endif #ifdef HAVE_INODE_GET_CTIME info->msg_info.key.i_ctime.tv_sec = inode_get_ctime(path->dentry->d_inode).tv_sec; info->msg_info.key.i_ctime.tv_nsec = inode_get_ctime(path->dentry->d_inode).tv_nsec; #else info->msg_info.key.i_ctime.tv_sec = path->dentry->d_inode->i_ctime.tv_sec; info->msg_info.key.i_ctime.tv_nsec = path->dentry->d_inode->i_ctime.tv_nsec; #endif info->pid_version = pid_version; if ((flags & O_ACCMODE) <= O_RDWR) { flags += 1; } info->flags = flags; info->low = low; info->high = high; return true; } static inline bool make_file_context_info_with_inode(file_context_info_t *info, const struct inode *inode, uint64_t unique_pid) { make_key_from_inode(&info->msg_info.key.file_key, inode); #ifdef HAVE_INODE_GET_MTIME info->msg_info.key.i_mtime.tv_sec = inode_get_mtime(inode).tv_sec; info->msg_info.key.i_mtime.tv_nsec = inode_get_mtime(inode).tv_nsec; #else info->msg_info.key.i_mtime.tv_sec = inode->i_mtime.tv_sec; info->msg_info.key.i_mtime.tv_nsec = inode->i_mtime.tv_nsec; #endif #ifdef HAVE_INODE_GET_CTIME info->msg_info.key.i_ctime.tv_sec = inode_get_ctime(inode).tv_sec; info->msg_info.key.i_ctime.tv_nsec = inode_get_ctime(inode).tv_nsec; #else info->msg_info.key.i_ctime.tv_sec = inode->i_ctime.tv_sec; info->msg_info.key.i_ctime.tv_nsec = inode->i_ctime.tv_nsec; #endif // currently this function uses unique_pid only info->unique_pid = unique_pid; return true; } #ifndef NSFS_MAGIC #define NSFS_MAGIC 0x6e736673 #endif #ifndef SYSFS_MAGIC #define SYSFS_MAGIC 0x62656572 #endif #ifndef PROC_SUPER_MAGIC #define PROC_SUPER_MAGIC 0x9fa0 #endif #ifndef DEBUGFS_MAGIC #define DEBUGFS_MAGIC 0x64626720 #endif #ifndef SECURITYFS_MAGIC #define SECURITYFS_MAGIC 0x73636673 #endif #ifndef CGROUP_SUPER_MAGIC #define CGROUP_SUPER_MAGIC 0x27e0eb #endif #ifndef CGROUP2_SUPER_MAGIC #define CGROUP2_SUPER_MAGIC 0x63677270 #endif #ifndef BPF_FS_MAGIC #define BPF_FS_MAGIC 0xcafe4a11 #endif #ifndef TRACEFS_MAGIC #define TRACEFS_MAGIC 0x74726163 #endif #ifndef FUSECTL_SUPER_MAGIC #define FUSECTL_SUPER_MAGIC 0x65735543 #endif #ifndef PSTOREFS_MAGIC #define PSTOREFS_MAGIC 0x6165676C #endif #ifndef CONFIGFS_MAGIC #define CONFIGFS_MAGIC 0x62656570 #endif #ifndef HUGETLBFS_MAGIC #define HUGETLBFS_MAGIC 0x958458f6 #endif #ifndef MQUEUE_MAGIC #define MQUEUE_MAGIC 0x19800202 #endif #ifndef DEVPTS_SUPER_MAGIC #define DEVPTS_SUPER_MAGIC 0x1cd1 #endif #ifndef SELINUX_MAGIC #define SELINUX_MAGIC 0xf97cff8c #endif static inline bool inode_is_usable(const struct inode *inode) { if (!inode) { return false; } if (!inode->i_sb) { return false; } return true; } // Checks for bare minimum requirements for 'path' to be any sort of reasonable static inline bool path_is_usable(const struct path *path) { struct dentry *dentry; if (!path->mnt) return false; dentry = path->dentry; if (!dentry) { return false; } return inode_is_usable(dentry->d_inode); } static inline int magic_ok(unsigned long magic) { return magic != BPF_FS_MAGIC && magic != CGROUP_SUPER_MAGIC && magic != CGROUP2_SUPER_MAGIC && magic != CONFIGFS_MAGIC && magic != DEBUGFS_MAGIC && magic != DEVPTS_SUPER_MAGIC && magic != FUSECTL_SUPER_MAGIC && magic != HUGETLBFS_MAGIC && magic != MQUEUE_MAGIC && magic != NSFS_MAGIC && magic != PROC_SUPER_MAGIC && magic != PSTOREFS_MAGIC && magic != SECURITYFS_MAGIC && magic != SELINUX_MAGIC && magic != SYSFS_MAGIC && magic != TRACEFS_MAGIC ; } static inline int sb_ok(const struct super_block *sb) { return sb && magic_ok(sb->s_magic); } static inline bool check_if_usable_inode_valid(const struct inode *inode) { umode_t mode; if (!sb_ok(inode->i_sb)) { return false; } mode = inode->i_mode; if ((S_ISREG(mode)) || (S_ISDIR(mode))) return true; else return false; } static inline bool inode_is_valid(const struct inode *inode) { if (!inode_is_usable(inode)) { return false; } return check_if_usable_inode_valid(inode); } static inline bool path_is_valid(const struct path *path) { if (!path_is_usable(path)) { return false; } return check_if_usable_inode_valid(path->dentry->d_inode); } static inline bool file_is_valid(struct file* f) { return path_is_valid(&f->f_path); }