diff --git a/.github/builder_containers/kernel-3.0.101.Dockerfile b/.github/builder_containers/kernel-3.0.101.Dockerfile deleted file mode 100644 index d46fa44..0000000 --- a/.github/builder_containers/kernel-3.0.101.Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM ubuntu:14.04 - -RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget - -RUN wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.0.101.tar.xz -O kernel.tar.xz -RUN tar -xf kernel.tar.xz -RUN rm -f kernel.tar.xz -RUN /bin/bash -c "mv linux-* linux" - -WORKDIR /linux -RUN make defconfig -RUN make -j$(nproc) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 65ce0ca..009f86b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -106,7 +106,6 @@ jobs: - 4.19.322 - 4.4.302 - 3.10.108 - - 3.0.101 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/Kbuild b/Kbuild index c675e87..de094d3 100644 --- a/Kbuild +++ b/Kbuild @@ -1,3 +1,3 @@ obj-m := kyoutubeUnblock.o -kyoutubeUnblock-objs := src/kytunblock.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/kargs.o src/tls.o src/getopt.o src/inet_ntop.o src/args.o deps/cyclone/aes.o deps/cyclone/cpu_endian.o deps/cyclone/ecb.o deps/cyclone/gcm.o deps/cyclone/hkdf.o deps/cyclone/hmac.o deps/cyclone/sha256.o +kyoutubeUnblock-objs := src/kytunblock.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/tls.o src/getopt.o src/inet_ntop.o src/args.o deps/cyclone/aes.o deps/cyclone/cpu_endian.o deps/cyclone/ecb.o deps/cyclone/gcm.o deps/cyclone/hkdf.o deps/cyclone/hmac.o deps/cyclone/sha256.o ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement -I$(src)/src -I$(src)/deps/cyclone/include diff --git a/src/kargs.c b/src/kargs.c deleted file mode 100644 index 9fb0e42..0000000 --- a/src/kargs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - youtubeUnblock - https://github.com/Waujito/youtubeUnblock - - Copyright (C) 2024-2025 Vadim Vetrov - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "config.h" -#include "types.h" -#include -#include "types.h" -#include "args.h" -#include "logging.h" - -/** -* Defined in kyoutubeUnblock.c -*/ -extern struct spinlock hot_config_spinlock; -extern atomic_t hot_config_counter; -extern atomic_t hot_config_rep; -extern struct mutex config_free_mutex; - -#define MAX_ARGC 1024 -static char *argv[MAX_ARGC]; - -static int params_set(const char *cval, const struct kernel_param *kp) { - int ret; - ret = mutex_trylock(&config_free_mutex); - if (ret == 0) - return -EBUSY; - - - int cv_len = strlen(cval); - if (cv_len >= 1 && cval[cv_len - 1] == '\n') { - cv_len--; - } - - const char *ytb_prefix = "youtubeUnblock "; - int ytbp_len = strlen(ytb_prefix); - int len = cv_len + ytbp_len; - - char *val = kmalloc(len + 1, GFP_KERNEL); // 1 for null-terminator - strncpy(val, ytb_prefix, ytbp_len); - strncpy(val + ytbp_len, cval, cv_len); - val[len] = '\0'; - - int argc = 0; - argv[argc++] = val; - - for (int i = 0; i < len; i++) { - if (val[i] == ' ') { - val[i] = '\0'; - - // safe because of null-terminator - if (val[i + 1] != ' ' && val[i + 1] != '\0') { - argv[argc++] = val + i + 1; - } - } - } - - spin_lock(&hot_config_spinlock); - // lock netfilter youtubeUnblock - atomic_set(&hot_config_rep, 1); - spin_unlock(&hot_config_spinlock); - - // lock config hot replacement process until all - // netfilter callbacks keep running - while (atomic_read(&hot_config_counter) > 0) {} - - ret = yparse_args(argc, argv); - - spin_lock(&hot_config_spinlock); - // relaunch youtubeUnblock - atomic_set(&hot_config_rep, 0); - spin_unlock(&hot_config_spinlock); - - kfree(val); - - mutex_unlock(&config_free_mutex); - return ret; -} - -static int params_get(char *buffer, const struct kernel_param *kp) { - size_t len = print_config(buffer, 4000); - return len; -} - -static const struct kernel_param_ops params_ops = { - .set = params_set, - .get = params_get, -}; - -module_param_cb(parameters, ¶ms_ops, NULL, 0664); diff --git a/src/kytunblock.c b/src/kytunblock.c index 08e3519..69c2cb8 100644 --- a/src/kytunblock.c +++ b/src/kytunblock.c @@ -63,12 +63,85 @@ MODULE_DESCRIPTION("Linux kernel module for youtubeUnblock"); static struct socket *rawsocket; static struct socket *raw6socket; -DEFINE_SPINLOCK(hot_config_spinlock); -DEFINE_MUTEX(config_free_mutex); -atomic_t hot_config_counter = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(hot_config_spinlock); +static DEFINE_MUTEX(config_free_mutex); +static atomic_t hot_config_counter = ATOMIC_INIT(0); // boolean flag for hot config replacement // if 1, youtubeUnblock should stop processing -atomic_t hot_config_rep = ATOMIC_INIT(0); +static atomic_t hot_config_rep = ATOMIC_INIT(0); + +#define MAX_ARGC 1024 +static char *argv[MAX_ARGC]; + +static int params_set(const char *cval, const struct kernel_param *kp) { + int ret; + ret = mutex_trylock(&config_free_mutex); + if (ret == 0) + return -EBUSY; + + + int cv_len = strlen(cval); + if (cv_len >= 1 && cval[cv_len - 1] == '\n') { + cv_len--; + } + + const char *ytb_prefix = "youtubeUnblock "; + int ytbp_len = strlen(ytb_prefix); + int len = cv_len + ytbp_len; + + char *val = kmalloc(len + 1, GFP_KERNEL); // 1 for null-terminator + strncpy(val, ytb_prefix, ytbp_len); + strncpy(val + ytbp_len, cval, cv_len); + val[len] = '\0'; + + int argc = 0; + argv[argc++] = val; + + for (int i = 0; i < len; i++) { + if (val[i] == ' ') { + val[i] = '\0'; + + // safe because of null-terminator + if (val[i + 1] != ' ' && val[i + 1] != '\0') { + argv[argc++] = val + i + 1; + } + } + } + + spin_lock(&hot_config_spinlock); + // lock netfilter youtubeUnblock + atomic_set(&hot_config_rep, 1); + spin_unlock(&hot_config_spinlock); + + // lock config hot replacement process until all + // netfilter callbacks keep running + while (atomic_read(&hot_config_counter) > 0) {} + + ret = yparse_args(argc, argv); + + spin_lock(&hot_config_spinlock); + // relaunch youtubeUnblock + atomic_set(&hot_config_rep, 0); + spin_unlock(&hot_config_spinlock); + + kfree(val); + + mutex_unlock(&config_free_mutex); + return ret; +} + +static int params_get(char *buffer, const struct kernel_param *kp) { + size_t len = print_config(buffer, 4000); + return len; +} + +static const struct kernel_param_ops params_ops = { + .set = params_set, + .get = params_get, +}; + +module_param_cb(parameters, ¶ms_ops, NULL, 0664); + static int open_raw_socket(void) { int ret = 0; @@ -475,16 +548,22 @@ static struct nf_hook_ops ykb_hook_ops[] = { } #endif }; +static const size_t ykb_hooks_sz = sizeof(ykb_hook_ops) / sizeof(struct nf_hook_ops); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) static int ykb_net_init(struct net *net) { - return nf_register_net_hooks(net, ykb_hook_ops, sizeof(ykb_hook_ops)); + int ret; + ret = nf_register_net_hooks(net, ykb_hook_ops, ykb_hooks_sz); + if (ret < 0) + return ret; + + return 0; } static void ykb_net_exit(struct net *net) { - nf_unregister_net_hooks(net, ykb_hook_ops, sizeof(ykb_hook_ops)); + nf_unregister_net_hooks(net, ykb_hook_ops, ykb_hooks_sz); } static struct pernet_operations ykb_pernet_ops = { @@ -504,12 +583,14 @@ static int __init ykb_init(void) { #endif ret = init_config(&config); - if (ret < 0) goto err; + if (ret < 0) { + goto err; + } ret = open_raw_socket(); if (ret < 0) { lgerror(ret, "ipv4 rawsocket initialization failed!"); - goto err; + goto err_config; } #ifndef NO_IPV6 @@ -523,7 +604,7 @@ static int __init ykb_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) ret = register_pernet_subsys(&ykb_pernet_ops); #else - ret = nf_register_hooks(ykb_hook_ops, sizeof(ykb_hook_ops)); + ret = nf_register_hooks(ykb_hook_ops, ykb_hooks_sz); #endif if (ret < 0) @@ -539,6 +620,8 @@ err_close_sock: #endif err_close4_sock: close_raw_socket(); +err_config: + free_config(config); err: return ret; } @@ -558,7 +641,7 @@ static void __exit ykb_destroy(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) unregister_pernet_subsys(&ykb_pernet_ops); #else - nf_unregister_hooks(ykb_hook_ops, sizeof(ykb_hook_ops)); + nf_unregister_hooks(ykb_hook_ops, ykb_hooks_sz); #endif diff --git a/src/mangle.c b/src/mangle.c index b1725e2..6434380 100644 --- a/src/mangle.c +++ b/src/mangle.c @@ -142,7 +142,7 @@ int process_packet(const struct packet_data *pd) { lgtrace_write(); lgtrace_wr("Transport payload: [ "); - for (int i = 0; i < min(16, transport_payload_len); i++) { + for (int i = 0; i < min((int)16, (int)transport_payload_len); i++) { lgtrace_wr("%02x ", transport_payload[i]); } lgtrace_wr("]"); @@ -224,7 +224,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra size_t fake_len = section->fake_sni_pkt_sz; if (section->synfake_len) - fake_len = min(section->synfake_len, fake_len); + fake_len = min((int)section->synfake_len, (int)fake_len); size_t payload_len = iph_len + tcph_len + fake_len; @@ -279,7 +279,6 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra if (vrd.target_sni) { lgdebug("Target SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr); - size_t sni_offset = vrd.sni_ptr - data; size_t target_sni_offset = vrd.target_sni_ptr - data; size_t payload_len = raw_payload_len; diff --git a/src/quic.c b/src/quic.c index 28e5da1..82050d3 100644 --- a/src/quic.c +++ b/src/quic.c @@ -366,8 +366,6 @@ int parse_quic_decrypted( const uint8_t *curptr = decrypted_message; ssize_t curptr_len = decrypted_message_len; ssize_t fret; - int ret; - struct tls_verdict tlsv = {0}; struct quic_frame_crypto fr_cr; uint8_t *crypto_message = calloc(AVAILABLE_MTU, 1); diff --git a/src/tls.c b/src/tls.c index eae6555..91287fc 100644 --- a/src/tls.c +++ b/src/tls.c @@ -45,7 +45,7 @@ int bruteforce_analyze_sni_str( for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { - max_domain_len = max(sne->domain_len, max_domain_len); + max_domain_len = max((int)sne->domain_len, max_domain_len); } size_t buf_size = max_domain_len + dlen + 1; @@ -274,7 +274,7 @@ struct tls_verdict analyze_tls_data( if (tls_vmajor != 0x03) break; message_ptr++; - uint8_t tls_vminor = *message_ptr; + // uint8_t tls_vminor = *message_ptr; message_ptr++; uint16_t message_length = ntohs(*(const uint16_t *)message_ptr); @@ -283,7 +283,7 @@ struct tls_verdict analyze_tls_data( const uint8_t *tls_message_data = message_ptr; // Since real length may be truncated use minimum of two - size_t tls_message_length = min(message_length, data_end - message_ptr); + size_t tls_message_length = min((int)message_length, (int)(data_end - message_ptr)); if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE) goto nextMessage;