shell bypass 403

Cubjrnet7 Shell


name : net_compat.h
/**
@file     net_compat.h
@brief    Network based events compat functions
@details  Copyright (c) 2025 Acronis International GmbH
@author   Denis Kopyrin ([email protected])
@since    $Id: $
*/

#pragma once

#ifdef KERNEL_MOCK
#include "mock/mock_net.h"
#endif

#include <linux/net.h>
#include <linux/socket.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/uio.h>

// It is kind of a magic variable for inet and inet6.
// If it is !0, it will refer to peer and if it is !1, it will always provide addr
#define PEER_LOCAL 0
#define PEER_REMOTE_ALWAYS 2

static inline int sock_to_addr(struct socket *sock, struct sockaddr_storage* storage, int peer)
{
#ifdef HAVE_LEN_IN_SOCK_GETNAME
	int addr_len;
	const int error = sock->ops->getname(sock, (struct sockaddr*) storage, &addr_len, peer);
	if (error)
		return 0;
	else
		return addr_len;
#else
	int addr_len = sock->ops->getname(sock, (struct sockaddr*) storage, peer);
	if (addr_len < 0)
		return 0;
	else
		return addr_len;
#endif
}

#ifndef HAVE_IOV_ITER
// Tries to copy at least 'len' iov from userspace.
// Inspired by 'memcpy_fromiovecend' but improved to provide 'iov_len' check and return 'len'
static inline size_t copy_from_user_iovec_safe(unsigned char *kdata, const struct iovec *iov, size_t iov_len, size_t len)
{
	size_t orig_len = len;
	while (len > 0 && iov_len) {
		size_t copy = len;
		if (copy > iov->iov_len)
			copy = iov->iov_len;

		if (copy_from_user(kdata, iov->iov_base, copy))
			return 0;

		len -= copy;
		kdata += copy;
		iov++;
		iov_len--;
	}

	// len will go to 0 and indicates of data amount left to copy, hence actually copied is difference below
	return orig_len - len;
}
#endif

#if defined(HAVE_IOV_ITER_IN_MSGHDR) && !defined(HAVE_IOV_ITER_REVERT)
// Copied from Linux 4.11 without support for ITER_PIPE
static void iov_iter_revert(struct iov_iter *i, size_t unroll)
{
	if (!unroll)
		return;

	i->count += unroll;
	if (unroll <= i->iov_offset) {
		i->iov_offset -= unroll;
		return;
	}
	unroll -= i->iov_offset;
	if (i->type & ITER_BVEC) {
		const struct bio_vec *bvec = i->bvec;
		while (1) {
			size_t n = (--bvec)->bv_len;
			i->nr_segs++;
			if (unroll <= n) {
				i->bvec = bvec;
				i->iov_offset = n - unroll;
				return;
			}
			unroll -= n;
		}
	} else { /* same logics for iovec and kvec */
		const struct iovec *iov = i->iov;
		while (1) {
			size_t n = (--iov)->iov_len;
			i->nr_segs++;
			if (unroll <= n) {
				i->iov = iov;
				i->iov_offset = n - unroll;
				return;
			}
			unroll -= n;
		}
	}
}
#endif

static inline size_t msg_data_peek(struct msghdr *msg, void* buf, size_t amount)
{
	size_t copied_size = 0;

#ifdef HAVE_IOV_ITER_IN_MSGHDR
	struct iov_iter* iter = &msg->msg_iter;

	// Do not try peek tricks with ITER_PIPE! It will discard the bytes from pipe so do not allow peeking at all.
#ifdef HAVE_IOV_ITER_IS_PIPE
	if (iov_iter_is_pipe(iter))
		return 0;
#elif defined(HAVE_IOV_ITER_PIPE)
	if (iter->type & ITER_PIPE)
		return 0;
#endif

	copied_size = copy_from_iter(buf, amount, iter);
	if (copied_size > 0) {
		iov_iter_revert(iter, copied_size);
	}
#else
	if (msg->msg_iov)
		copied_size = copy_from_user_iovec_safe(buf, msg->msg_iov, msg->msg_iovlen, amount);
	else
		copied_size = 0;
#endif

	return copied_size;
}

© 2025 Cubjrnet7