/
usr
/
src
/
file_protector-1.1-1506
/
File Upload :
llllll
Current File: //usr/src/file_protector-1.1-1506/module_rundown_protection.c
/** @file module_rundown_protection.c @brief Global module rundown protection used for safe syscalls handling @details Copyright (c) 2022 Acronis International GmbH @author Denis Kopyrin (Denis.Kopyrin@acronis.com) @since $Id: $ */ #include "rundown_protection.h" #include "module_ref.h" #include <linux/module.h> #include <linux/spinlock.h> typedef struct { rundown_protection_t rundown_protection; // 'spinlock' protects flags below spinlock_t spinlock; bool active; bool referenced; } mod_rundown_protection_t; static mod_rundown_protection_t mod_rundown_protection; static void mod_rundown_protection_finalizer(void *ctx) { bool active, referenced; mod_rundown_protection_t *mrp = (mod_rundown_protection_t*) ctx; IPRINTF(""); spin_lock(&mrp->spinlock); active = mrp->active; referenced = mrp->referenced; if (!active) { mrp->referenced = false; } spin_unlock(&mrp->spinlock); IPRINTF("active=%d, referenced=%d", active, referenced); if (active) { IPRINTF("mod is currently active, doing nothing and considering finalizer spurious"); return; } if (referenced) { MODULE_PUT(); } else { IPRINTF("module is not referenced already"); } } void __init mod_rundown_protection_init(bool ready) { rundown_protection_init(&mod_rundown_protection.rundown_protection, mod_rundown_protection_finalizer, &mod_rundown_protection, ready); spin_lock_init(&mod_rundown_protection.spinlock); mod_rundown_protection.referenced = false; mod_rundown_protection.active = false; } bool mod_rundown_protection_lock(void) { return rundown_protection_lock(&mod_rundown_protection.rundown_protection); } void mod_rundown_protection_unlock(void) { return rundown_protection_unlock(&mod_rundown_protection.rundown_protection); } void mod_rundown_protection_set_rundown_active(void) { int64_t pending_count = 0; bool need_unreference = false; IPRINTF(""); // Notice that during 'set_rundown_active' spurious finalizer might be called rundown_protection_set_rundown_active(&mod_rundown_protection.rundown_protection); // Because 'mod_rundown_protection.active=false' is set after 'set_rundown_active' is done, finalizer might be missed. // In this case, we might have to unreference from here too if 'get_pending_count' is 0. spin_lock(&mod_rundown_protection.spinlock); mod_rundown_protection.active = false; pending_count = rundown_protection_get_pending_count(&mod_rundown_protection.rundown_protection); if (0 == pending_count) { need_unreference = mod_rundown_protection.referenced; mod_rundown_protection.referenced = false; } spin_unlock(&mod_rundown_protection.spinlock); IPRINTF("pending_count=%lld need_unreference=%d", pending_count, need_unreference); if (need_unreference) { MODULE_PUT(); } } void mod_rundown_protection_wait_for_rundown(void) { return rundown_protection_wait_for_rundown(&mod_rundown_protection.rundown_protection); } bool mod_rundown_protection_wait_for_rundown_timeout(unsigned long timeout_jiffies) { return rundown_protection_wait_for_rundown_timeout(&mod_rundown_protection.rundown_protection, timeout_jiffies); } void mod_rundown_protection_set_ready(void) { bool module_was_already_referenced; IPRINTF(""); MODULE_GET(); spin_lock(&mod_rundown_protection.spinlock); mod_rundown_protection.active = true; module_was_already_referenced = mod_rundown_protection.referenced; mod_rundown_protection.referenced = true; spin_unlock(&mod_rundown_protection.spinlock); rundown_protection_set_ready(&mod_rundown_protection.rundown_protection); IPRINTF("module_was_already_referenced=%d", module_was_already_referenced); if (module_was_already_referenced) { MODULE_PUT(); } }
Copyright ©2k19 -
Hexid
|
Tex7ure