tkernel: initial support and nonpriv_bind

Upstream: no

- /proc/tkernel/nonpriv_netbind:
Contain list of ports allowed for nonpriv bind

echo +80 > /proc/tkernel/nonpriv_netbind
echo -80 > /proc/tkernel/nonpriv_netbind

Controls whether allow/deny nonpriv user bind to specified port.

Signed-off-by: Samuel Liao <samuelliao@tencent.com>
Signed-off-by: Xiaoming Gao <newtongao@tencent.com>
Signed-off-by: katrinzhou <katrinzhou@tencent.com>
Signed-off-by: Kairui Song <kasong@tencent.com>
This commit is contained in:
katrinzhou 2022-04-14 12:27:11 +08:00 committed by Kairui Song
parent 95c98461d1
commit 0585394287
10 changed files with 148 additions and 2 deletions

18
include/linux/tkernel.h Normal file
View File

@ -0,0 +1,18 @@
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
extern struct proc_dir_entry *proc_tkernel;
extern const struct ctl_path tkernel_ctl_path[];
/* prot_sock_flag */
#ifdef CONFIG_TKERNEL_NONPRIV_NETBIND
extern bool nonpriv_prot_sock_flag[];
static inline bool check_nonpriv_prot_sock(int num)
{
return nonpriv_prot_sock_flag[num];
}
#else
static inline bool check_nonpriv_prot_sock(int num)
{
return false;
}
#endif

View File

@ -1968,6 +1968,7 @@ config ASN1
functions to call on what tags.
source "kernel/Kconfig.locks"
source "kernel/Kconfig.tkernel"
config ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
bool

2
kernel/Kconfig.tkernel Normal file
View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
source "kernel/tkernel/Kconfig"

View File

@ -114,6 +114,7 @@ obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call_inline.o
obj-$(CONFIG_CFI_CLANG) += cfi.o
obj-$(CONFIG_TKERNEL) += tkernel/
obj-$(CONFIG_PERF_EVENTS) += events/

12
kernel/tkernel/Kconfig Normal file
View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig TKERNEL
bool "Tencent Kernel Features"
default n
if TKERNEL
config TKERNEL_NONPRIV_NETBIND
bool "Allow non-privileged user to bind specific low ports"
default n
endif

2
kernel/tkernel/Makefile Normal file
View File

@ -0,0 +1,2 @@
obj-$(CONFIG_TKERNEL) += base.o
obj-$(CONFIG_TKERNEL_NONPRIV_NETBIND) += netbind.o

19
kernel/tkernel/base.c Normal file
View File

@ -0,0 +1,19 @@
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/tkernel.h>
#include <linux/init.h>
struct proc_dir_entry *proc_tkernel;
EXPORT_SYMBOL(proc_tkernel);
static struct ctl_table placeholder_vars[] = {
{},
};
static int __init tkernel_init(void)
{
proc_tkernel = proc_mkdir("tkernel", NULL);
register_sysctl_init("tkernel", placeholder_vars);
return 0;
}
early_initcall(tkernel_init);

89
kernel/tkernel/netbind.c Normal file
View File

@ -0,0 +1,89 @@
#include <linux/tkernel.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <net/sock.h>
bool nonpriv_prot_sock_flag[PROT_SOCK];
EXPORT_SYMBOL(nonpriv_prot_sock_flag);
static int netbind_proc_show(struct seq_file *m, void *v)
{
int i;
for (i = 1; i < PROT_SOCK; i++) {
if (nonpriv_prot_sock_flag[i])
seq_printf(m, "%d\n", i);
}
return 0;
}
static int netbind_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, netbind_proc_show, NULL);
}
static ssize_t netbind_proc_write(struct file *file, const char __user *buf,
size_t length, loff_t *ppos)
{
int port, en;
char *buffer, *p;
int err;
if (!buf || length > PAGE_SIZE)
return -EINVAL;
buffer = (char *)__get_free_page(GFP_KERNEL);
if (!buffer)
return -ENOMEM;
err = -EFAULT;
if (copy_from_user(buffer, buf, length))
goto out;
err = -EINVAL;
if (length < PAGE_SIZE)
buffer[length] = '\0';
else if (buffer[PAGE_SIZE-1])
goto out;
en = 1;
p = buffer;
if (*p == '+') {
p++;
} else if (*p == '-') {
en = 0;
p++;
}
if (*p < '0' || *p > '9')
goto out;
port = simple_strtoul(p, &p, 0);
if (*p != '\n' && *p != '\r' && *p != '\0')
goto out;
if (port <= 0 || port >= PROT_SOCK)
goto out;
nonpriv_prot_sock_flag[port] = en;
err = length;
out:
free_page((unsigned long)buffer);
return err;
}
static const struct proc_ops netbind_proc_ops = {
.proc_open = netbind_proc_open,
.proc_read = seq_read,
.proc_write = netbind_proc_write,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int __init nonpriv_netbind_init(void)
{
proc_create("nonpriv_netbind", 0, proc_tkernel, &netbind_proc_ops);
return 0;
}
late_initcall(nonpriv_netbind_init);

View File

@ -121,6 +121,7 @@
#include <net/compat.h>
#include <trace/events/sock.h>
#include <linux/tkernel.h>
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
@ -505,7 +506,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
snum = ntohs(addr->sin_port);
err = -EACCES;
if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) &&
snum && inet_port_requires_bind_service(net, snum) &&
snum && inet_port_requires_bind_service(net, snum) && !check_nonpriv_prot_sock(snum) &&
!ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
goto out;

View File

@ -67,6 +67,7 @@
#include <linux/uaccess.h>
#include <linux/mroute6.h>
#include <linux/tkernel.h>
#include "ip6_offload.h"
@ -296,7 +297,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
snum = ntohs(addr->sin6_port);
if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) &&
snum && inet_port_requires_bind_service(net, snum) &&
snum && inet_port_requires_bind_service(net, snum) && !check_nonpriv_prot_sock(snum) &&
!ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
return -EACCES;