shell bypass 403

Cubjrnet7 Shell

: /usr/src/file_protector-1.1-1553/ [ drwxr-xr-x ]

name : rundown_protection.c
/**
 @file     rundown_protection.cpp
 @brief    Rundown Protection implementation for Linux kernel
 @details  Copyright (c) 2022 Acronis International GmbH
 @author   Denis Kopyrin ([email protected])
 @since    $Id: $
 */

#include "rundown_protection.h"

#include "debug.h"

#define RP_RUNDOWN_ACTIVE 1
#define RP_RUNDOWN_COUNT_SHIFT 1
#define RP_RUNDOWN_COUNT_INC (1 << RP_RUNDOWN_COUNT_SHIFT)

#define RP_LOG IPRINTF

static inline
void rundown_wait_block_init(rundown_wait_block_t *rwb, rundown_protection_finalizer_t finalizer, void *finalizer_ctx) {
	atomic64_set(&rwb->ref_cnt, 0);
	init_waitqueue_head(&rwb->wait_queue);
	rwb->finalizer = finalizer;
	rwb->finalizer_ctx = finalizer_ctx;
}

static inline
void rundown_wait_block_wait(rundown_wait_block_t *rwb) {
	wait_event(rwb->wait_queue, 0 == atomic64_read(&rwb->ref_cnt));
}

static inline
long rundown_wait_block_wait_timeout(rundown_wait_block_t *rwb, unsigned long timeout_jiffies) {
	return wait_event_timeout(rwb->wait_queue, 0 == atomic64_read(&rwb->ref_cnt), timeout_jiffies);
}

static inline
int64_t rundown_wait_block_decrement_count_and_notify(rundown_wait_block_t *rwb) {
	int64_t leftCount = atomic64_sub_return(1, &rwb->ref_cnt);
	if (0 == leftCount) {
		wake_up(&rwb->wait_queue);
		if (rwb->finalizer) {
			IPRINTF("Invoking finalizer");
			rwb->finalizer(rwb->finalizer_ctx);
			IPRINTF("Finalizer completed");
		}
	}

	return leftCount;
}

static inline
void rundown_wait_block_add_count(rundown_wait_block_t *rwb, int64_t cnt) {
	atomic64_add(cnt, &rwb->ref_cnt);
}

static inline
int64_t rundown_wait_block_get_count(rundown_wait_block_t *rwb) {
	return atomic64_read(&rwb->ref_cnt);
}

void simple_rundown_protection_init(simple_rundown_protection_t *srp, rundown_protection_finalizer_t finalizer, void *finalizer_ctx, bool ready) {
	atomic64_set(&srp->data, ready ? 0 : RP_RUNDOWN_ACTIVE);
	rundown_wait_block_init(&srp->wait_block, finalizer, finalizer_ctx);
}

bool simple_rundown_protection_lock(simple_rundown_protection_t *srp) {
	int64_t old_value, new_value;
	do {
		old_value = atomic64_read(&srp->data);
		if (old_value & RP_RUNDOWN_ACTIVE)
			return false;

		new_value = old_value + RP_RUNDOWN_COUNT_INC;
	} while(old_value != atomic64_cmpxchg(&srp->data, old_value, new_value));

	return true;
}

void simple_rundown_protection_unlock(simple_rundown_protection_t *srp) {
	int64_t value;
	while (true) {
		value = atomic64_read(&srp->data);
		if (!(value & RP_RUNDOWN_ACTIVE)) {
			// active
			int64_t new_value = value - RP_RUNDOWN_COUNT_INC;
			if (value == atomic64_cmpxchg(&srp->data, value, new_value))
				return;
		} else {
			// rundown
			int64_t cnt;
			RP_LOG("releasing count...");
			cnt = rundown_wait_block_decrement_count_and_notify(&srp->wait_block);
			RP_LOG("released count, left=%lld", cnt);
			return;
		}
	}
}

void simple_rundown_protection_set_rundown_active(simple_rundown_protection_t *srp) {
	int64_t count;
	int64_t value = atomic64_cmpxchg(&srp->data, 0, RP_RUNDOWN_ACTIVE);

	RP_LOG("");
	if (value & RP_RUNDOWN_ACTIVE)
		return;

	do {
		value = atomic64_read(&srp->data);
	} while(value != atomic64_cmpxchg(&srp->data, value, RP_RUNDOWN_ACTIVE));

	count = value >> RP_RUNDOWN_COUNT_SHIFT;
	rundown_wait_block_add_count(&srp->wait_block, count);

	RP_LOG("switched block count, left to wait for %lld unlocks", count);
}

void simple_rundown_protection_wait_for_rundown(simple_rundown_protection_t *srp) {
	RP_LOG("waiting...");
	rundown_wait_block_wait(&srp->wait_block);
	RP_LOG("waiting done");
}

static const char *convert_wait_result_to_string(long ret) {
	if (0 == ret) {
		return "timeout";
	} else if (ret < 0) {
		return "interrupted";
	} else {
		return "ok";
	}
}

bool simple_rundown_protection_wait_for_rundown_timeout(simple_rundown_protection_t *srp, unsigned long timeout_jiffies) {
	long res;

	RP_LOG("waiting...");
	res = rundown_wait_block_wait_timeout(&srp->wait_block, timeout_jiffies);
	RP_LOG("waiting done : %s[%ld]", convert_wait_result_to_string(res), res);

	return res > 0;
}

void simple_rundown_protection_set_ready(simple_rundown_protection_t *srp) {
	atomic64_set(&srp->data, 0);
}

int64_t simple_rundown_protection_get_pending_count(simple_rundown_protection_t *srp) {
	return rundown_wait_block_get_count(&srp->wait_block);
}

© 2025 Cubjrnet7