fixed unmount

This commit is contained in:
g2px1 2025-06-15 10:07:35 +00:00
parent f5cabb007f
commit 96ba11d9b2

View File

@ -1,4 +1,3 @@
// libfs.c
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
@ -7,6 +6,9 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/list.h>
#include <linux/fs_context.h>
#include <linux/err.h>
#define LIBFS_MAGIC 0xA0B0C0D0 #define LIBFS_MAGIC 0xA0B0C0D0
#define LIBFS_BOOKS_MODE 01777 #define LIBFS_BOOKS_MODE 01777
@ -14,9 +16,8 @@
#define LIBFS_SUBDIR_MODE 01777 #define LIBFS_SUBDIR_MODE 01777
static struct super_block *libfs_sb; static struct super_block *libfs_sb;
// Track books inode to monitor link targets
static struct inode *books_inode = NULL; static struct inode *books_inode = NULL;
static struct vfsmount *libfs_mnt;
static const struct super_operations libfs_sops = { static const struct super_operations libfs_sops = {
.statfs = simple_statfs, .statfs = simple_statfs,
@ -39,7 +40,7 @@ static struct inode *libfs_get_inode(struct super_block *sb, umode_t mode) {
if (S_ISDIR(mode)) { if (S_ISDIR(mode)) {
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
} else { } else {
inode->i_fop = &libfs_file_ops; // fallback inode->i_fop = &libfs_file_ops;
} }
inode->i_mode = mode; inode->i_mode = mode;
return inode; return inode;
@ -49,9 +50,51 @@ static bool is_protected_dentry(struct dentry *dentry) {
return (strcmp(dentry->d_name.name, "books") == 0 || strcmp(dentry->d_name.name, "authors") == 0); return (strcmp(dentry->d_name.name, "books") == 0 || strcmp(dentry->d_name.name, "authors") == 0);
} }
struct cleanup_ctx {
struct inode *victim;
};
static void libfs_cleanup_links(struct inode *victim)
{
struct dentry *root = libfs_sb->s_root;
struct qstr authors_q = QSTR_INIT("authors", 7);
struct dentry *authors = d_lookup(root, &authors_q);
if (!authors || d_really_is_negative(authors)) {
dput(authors);
return;
}
// Здесь конкретный пример: если ты сам знаешь имя линка на victim
// То можешь через d_lookup() найти его и удалить
struct qstr filename = QSTR_INIT("some_symlink", 12);
struct dentry *maybe_link = d_lookup(authors, &filename);
if (maybe_link && maybe_link->d_inode == victim) {
inode_lock(authors->d_inode);
vfs_unlink(NULL, authors->d_inode, maybe_link, NULL);
inode_unlock(authors->d_inode);
}
dput(maybe_link);
dput(authors);
}
static int libfs_unlink(struct inode *dir, struct dentry *dentry) {
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
return -EPERM;
struct inode *victim = dentry->d_inode;
int ret = simple_unlink(dir, dentry);
if (ret == 0 && dir == books_inode) {
libfs_cleanup_links(victim);
}
return ret;
}
static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) { static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) {
if (dir == libfs_sb->s_root->d_inode) { if (dir == libfs_sb->s_root->d_inode) {
return -EPERM; // no mkdir in root return -EPERM;
} }
struct inode *inode = libfs_get_inode(dir->i_sb, S_IFDIR | LIBFS_SUBDIR_MODE); struct inode *inode = libfs_get_inode(dir->i_sb, S_IFDIR | LIBFS_SUBDIR_MODE);
if (!inode) if (!inode)
@ -62,12 +105,6 @@ static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry
return 0; return 0;
} }
static int libfs_unlink(struct inode *dir, struct dentry *dentry) {
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
return -EPERM;
return simple_unlink(dir, dentry);
}
static int libfs_rmdir(struct inode *dir, struct dentry *dentry) { static int libfs_rmdir(struct inode *dir, struct dentry *dentry) {
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry)) if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
return -EPERM; return -EPERM;
@ -145,10 +182,15 @@ static struct file_system_type libfs_type = {
}; };
static int __init libfs_init(void) { static int __init libfs_init(void) {
return register_filesystem(&libfs_type); int ret = register_filesystem(&libfs_type);
if (ret)
return ret;
libfs_mnt = kern_mount(&libfs_type);
return PTR_ERR_OR_ZERO(libfs_mnt);
} }
static void __exit libfs_exit(void) { static void __exit libfs_exit(void) {
kern_unmount(libfs_mnt);
unregister_filesystem(&libfs_type); unregister_filesystem(&libfs_type);
} }