Re: block network access for certain users/groups

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Many Thnaks.
This is exactly what I have been looking for!
However if I compile the kernel module and try to load it that results
in a kernel hang that I can only escape by Alt-PrnScr-S-U-B, no matter
whether the module is loaded on boot time or in rl5. I have checked
all required kernel options and built it like the following (using
openSUSE 11.3):

make -C /lib/modules/`uname -r`/build SUBDIRS=~+/ modules || exit $?
install -m 644 nwusrblock-module /lib/modules/`uname
-r`/kernel/drivers/nwusrblock-module
/sbin/depmod -a
modprobe nwusrblock-modul



2010/8/26, Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx>:
> Tetsuo Handa wrote:
>> Elmar Stellnberger wrote:
>> > I need to block network access for certain users/groups, fully:
> Oh, I thought you want to partially block communication by specific user.
>
> You want to entirely block communication by specific user? Then, it is easy.
> You can block all socket syscalls by that user using LSM.
> I made an example LSM module which can be added as a loadable kernel module
> ( http://www.youtube.com/watch?v=wG8BTLMu5wo ). You can modify it as you
> like.
>
> You can compile and load below module provided that your kernel config has
> CONFIG_SECURITY_NETWORK=y .
>
> Did this module answer your question?
>
> Thanks.
> ----------------------------------------
> /*
>  * Uid-NoSock Linux Security Module
>  *
>  * Author: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx>
>  *
>  * This module blocks socket syscalls by specific UID. Use at your own risk.
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2, as
>  * published by the Free Software Foundation.
>  */
> /*
>  * Place this file (uid_nosock.c) in some directory and create Makefile
>  * containing a line
>  *
>  *  obj-m += uid_nosock.o
>  *
>  * and run
>  *
>  *   make SUBDIRS=directory_containing_this_file/ modules modules_install
>  *
>  */
> #include <linux/security.h>
> #ifndef CONFIG_SECURITY_NETWORK
> #error This module depends on CONFIG_SECURITY_NETWORK=y
> #endif
> #ifndef CONFIG_SECURITY
> #error This module depends on CONFIG_SECURITY=y
> #endif
> #ifndef CONFIG_KALLSYMS
> #error This module depends on CONFIG_KALLSYMS=y
> #endif
> #ifndef CONFIG_MODULES
> #error This module depends on CONFIG_MODULES=y
> #endif
> #include <linux/module.h>
> #include <linux/pid_namespace.h>
> #include <linux/mount.h>
> #include <linux/fs_struct.h>
> static struct security_operations original_security_ops;
>
> /* UID to block socket syscalls. */
> #define UID_NOSOCK_REJECT_UID 500
>
> static bool uid_nosock_deny(void)
> {
> 	return current_uid() == UID_NOSOCK_REJECT_UID;
> }
>
> static int uid_nosock_socket_create(int family, int type, int protocol,
> 				    int kern)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_create(family, type, protocol,
> 						   kern);
> }
>
> static int uid_nosock_socket_bind(struct socket *sock,
> 				  struct sockaddr *address, int addrlen)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_bind(sock, address, addrlen);
> }
>
> static int uid_nosock_socket_connect(struct socket *sock,
> 				     struct sockaddr *address, int addrlen)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_connect(sock, address, addrlen);
> }
>
> static int uid_nosock_socket_listen(struct socket *sock, int backlog)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_listen(sock, backlog);
> }
>
> static int uid_nosock_socket_accept(struct socket *sock,
> 				    struct socket *newsock)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_accept(sock, newsock);
> }
>
> static int uid_nosock_socket_sendmsg(struct socket *sock, struct msghdr
> *msg,
> 				     int size)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_sendmsg(sock, msg, size);
> }
>
> static int uid_nosock_socket_recvmsg(struct socket *sock, struct msghdr
> *msg,
> 				     int size, int flags)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_recvmsg(sock, msg, size, flags);
> }
>
> static int uid_nosock_socket_getsockname(struct socket *sock)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_getsockname(sock);
> }
>
> static int uid_nosock_socket_getpeername(struct socket *sock)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_getpeername(sock);
> }
>
> static int uid_nosock_socket_getsockopt(struct socket *sock, int level,
> 					int optname)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_getsockopt(sock, level, optname);
> }
>
> static int uid_nosock_socket_setsockopt(struct socket *sock, int level,
> 					int optname)
> {
> 	if (uid_nosock_deny())
> 		return -EPERM;
> 	return original_security_ops.socket_setsockopt(sock, level, optname);
> }
>
> /* Find symbols from /proc/kallsyms . */
> static void *__init uid_nosock_find_symbol(const char *keyline)
> {
> 	struct file *file;
> 	char *buf;
> 	unsigned long entry = 0;
> 	{
> 		struct fs_struct *fs = current->fs;
> 		struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
> 		struct path old_path;
> 		struct path new_path = { mnt, mnt->mnt_root };
> 		spin_lock(&fs->lock); /* was write_lock() till 2.6.35. */
> 		old_path = fs->pwd;
> 		fs->pwd = new_path;
> 		spin_unlock(&fs->lock);
> 		file = filp_open("kallsyms", O_RDONLY, 0);
> 		spin_lock(&fs->lock);
> 		fs->pwd = old_path;
> 		spin_unlock(&fs->lock);
> 	}
> 	if (IS_ERR(file))
> 		goto out;
> 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> 	if (buf) {
> 		int len;
> 		int offset = 0;
> 		while ((len = kernel_read(file, offset, buf,
> 					  PAGE_SIZE - 1)) > 0) {
> 			char *cp;
> 			buf[len] = '\0';
> 			cp = strrchr(buf, '\n');
> 			if (!cp)
> 				break;
> 			*(cp + 1) = '\0';
> 			offset += strlen(buf);
> 			cp = strstr(buf, keyline);
> 			if (!cp)
> 				continue;
> 			*cp = '\0';
> 			while (cp > buf && *(cp - 1) != '\n')
> 				cp--;
> 			entry = simple_strtoul(cp, NULL, 16);
> 			break;
> 		}
> 		kfree(buf);
> 	}
> 	filp_close(file, NULL);
> out:
> 	return (void *) entry;
> }
>
> /* Never mark this variable as __initdata . */
> static struct security_operations *uid_nosock_security_ops;
>
> /* Never mark this function as __init . */
> static int uid_nosock_addr_calculator(struct file *file)
> {
> 	return uid_nosock_security_ops->file_alloc_security(file);
> }
>
> static int __init uid_nosock_init(void)
> {
> 	struct security_operations **ptr;
> 	struct security_operations *ops;
> 	int i;
> 	const u8 *cp;
> 	/*
> 	 * Guess "struct security_operations *security_ops;".
> 	 * This trick depends on below assumptions.
> 	 *
> 	 * (1) Compiler generates identical code for security_file_alloc() and
> 	 *     uid_nosock_addr_calculator().
> 	 * (2) uid_nosock_security_ops is found within 128 bytes from
> 	 *     uid_nosock_addr_calculator, even if additional code (e.g. debug
> 	 *     symbols) is added.
> 	 * (3) It is safe to read 128 bytes from uid_nosock_addr_calculator.
> 	 * (4) uid_nosock_security_ops != Byte code except
> 	 *     uid_nosock_security_ops.
> 	 */
> 	cp = (const u8 *) uid_nosock_addr_calculator;
> 	for (i = 0; i < 128; i++) {
> 		if (sizeof(uid_nosock_security_ops) == sizeof(u32)) {
> 			if (*(u32 *) cp == (u32) &uid_nosock_security_ops)
> 				break;
> 		} else if (sizeof(uid_nosock_security_ops) == sizeof(u64)) {
> 			if (*(u64 *) cp == (u64) &uid_nosock_security_ops)
> 				break;
> 		}
> 		cp++;
> 	}
> 	if (i == 128) {
> 		printk(KERN_ERR
> 		       "Can't resolve uid_nosock_security_ops structure.\n");
> 		return -EINVAL;
> 	}
> 	cp = (const u8 *) uid_nosock_find_symbol(" security_file_alloc\n");
> 	if (!cp) {
> 		printk(KERN_ERR "Can't resolve security_file_alloc().\n");
> 		return -EINVAL;
> 	}
> 	/* This should be "struct security_operations *security_ops;". */
> 	ptr = *(struct security_operations ***) (cp + i);
> 	if (!ptr) {
> 		printk(KERN_ERR "Can't resolve security_ops structure.\n");
> 		return -EINVAL;
> 	}
> 	ops = *ptr;
> 	if (!ops) {
> 		printk(KERN_ERR "No security_operations registered.\n");
> 		return -EINVAL;
> 	}
> 	memmove(&original_security_ops, ops, sizeof(original_security_ops));
> 	smp_mb();
> 	BUG_ON(ops->socket_create == uid_nosock_socket_create ||
> 	       ops->socket_bind == uid_nosock_socket_bind ||
> 	       ops->socket_connect == uid_nosock_socket_connect ||
> 	       ops->socket_listen == uid_nosock_socket_listen ||
> 	       ops->socket_accept == uid_nosock_socket_accept ||
> 	       ops->socket_sendmsg == uid_nosock_socket_sendmsg ||
> 	       ops->socket_recvmsg == uid_nosock_socket_recvmsg ||
> 	       ops->socket_getsockname == uid_nosock_socket_getsockname ||
> 	       ops->socket_getpeername == uid_nosock_socket_getpeername ||
> 	       ops->socket_getsockopt == uid_nosock_socket_getsockopt ||
> 	       ops->socket_setsockopt == uid_nosock_socket_setsockopt);
> 	ops->socket_create = uid_nosock_socket_create;
> 	ops->socket_bind = uid_nosock_socket_bind;
> 	ops->socket_connect = uid_nosock_socket_connect;
> 	ops->socket_listen = uid_nosock_socket_listen;
> 	ops->socket_accept = uid_nosock_socket_accept;
> 	ops->socket_sendmsg = uid_nosock_socket_sendmsg;
> 	ops->socket_recvmsg = uid_nosock_socket_recvmsg;
> 	ops->socket_getsockname = uid_nosock_socket_getsockname;
> 	ops->socket_getpeername = uid_nosock_socket_getpeername;
> 	ops->socket_getsockopt = uid_nosock_socket_getsockopt;
> 	ops->socket_setsockopt = uid_nosock_socket_setsockopt;
> 	printk(KERN_INFO "Uid-Nosock: Blocking socket syscalls by uid=%u.\n",
> 	       UID_NOSOCK_REJECT_UID);
> 	return 0;
> }
>
> module_init(uid_nosock_init);
> MODULE_LICENSE("GPL");
>
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux