cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xt_owner.c (4007B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Kernel module to match various things tied to sockets associated with
      4 * locally generated outgoing packets.
      5 *
      6 * (C) 2000 Marc Boucher <marc@mbsi.ca>
      7 *
      8 * Copyright © CC Computer Consultants GmbH, 2007 - 2008
      9 */
     10#include <linux/module.h>
     11#include <linux/skbuff.h>
     12#include <linux/file.h>
     13#include <linux/cred.h>
     14
     15#include <net/sock.h>
     16#include <net/inet_sock.h>
     17#include <linux/netfilter/x_tables.h>
     18#include <linux/netfilter/xt_owner.h>
     19
     20static int owner_check(const struct xt_mtchk_param *par)
     21{
     22	struct xt_owner_match_info *info = par->matchinfo;
     23	struct net *net = par->net;
     24
     25	if (info->match & ~XT_OWNER_MASK)
     26		return -EINVAL;
     27
     28	/* Only allow the common case where the userns of the writer
     29	 * matches the userns of the network namespace.
     30	 */
     31	if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) &&
     32	    (current_user_ns() != net->user_ns))
     33		return -EINVAL;
     34
     35	/* Ensure the uids are valid */
     36	if (info->match & XT_OWNER_UID) {
     37		kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
     38		kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
     39
     40		if (!uid_valid(uid_min) || !uid_valid(uid_max) ||
     41		    (info->uid_max < info->uid_min) ||
     42		    uid_lt(uid_max, uid_min)) {
     43			return -EINVAL;
     44		}
     45	}
     46
     47	/* Ensure the gids are valid */
     48	if (info->match & XT_OWNER_GID) {
     49		kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
     50		kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
     51
     52		if (!gid_valid(gid_min) || !gid_valid(gid_max) ||
     53		    (info->gid_max < info->gid_min) ||
     54		    gid_lt(gid_max, gid_min)) {
     55			return -EINVAL;
     56		}
     57	}
     58
     59	return 0;
     60}
     61
     62static bool
     63owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
     64{
     65	const struct xt_owner_match_info *info = par->matchinfo;
     66	const struct file *filp;
     67	struct sock *sk = skb_to_full_sk(skb);
     68	struct net *net = xt_net(par);
     69
     70	if (!sk || !sk->sk_socket || !net_eq(net, sock_net(sk)))
     71		return (info->match ^ info->invert) == 0;
     72	else if (info->match & info->invert & XT_OWNER_SOCKET)
     73		/*
     74		 * Socket exists but user wanted ! --socket-exists.
     75		 * (Single ampersands intended.)
     76		 */
     77		return false;
     78
     79	filp = sk->sk_socket->file;
     80	if (filp == NULL)
     81		return ((info->match ^ info->invert) &
     82		       (XT_OWNER_UID | XT_OWNER_GID)) == 0;
     83
     84	if (info->match & XT_OWNER_UID) {
     85		kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
     86		kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
     87		if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
     88		     uid_lte(filp->f_cred->fsuid, uid_max)) ^
     89		    !(info->invert & XT_OWNER_UID))
     90			return false;
     91	}
     92
     93	if (info->match & XT_OWNER_GID) {
     94		unsigned int i, match = false;
     95		kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
     96		kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
     97		struct group_info *gi = filp->f_cred->group_info;
     98
     99		if (gid_gte(filp->f_cred->fsgid, gid_min) &&
    100		    gid_lte(filp->f_cred->fsgid, gid_max))
    101			match = true;
    102
    103		if (!match && (info->match & XT_OWNER_SUPPL_GROUPS) && gi) {
    104			for (i = 0; i < gi->ngroups; ++i) {
    105				kgid_t group = gi->gid[i];
    106
    107				if (gid_gte(group, gid_min) &&
    108				    gid_lte(group, gid_max)) {
    109					match = true;
    110					break;
    111				}
    112			}
    113		}
    114
    115		if (match ^ !(info->invert & XT_OWNER_GID))
    116			return false;
    117	}
    118
    119	return true;
    120}
    121
    122static struct xt_match owner_mt_reg __read_mostly = {
    123	.name       = "owner",
    124	.revision   = 1,
    125	.family     = NFPROTO_UNSPEC,
    126	.checkentry = owner_check,
    127	.match      = owner_mt,
    128	.matchsize  = sizeof(struct xt_owner_match_info),
    129	.hooks      = (1 << NF_INET_LOCAL_OUT) |
    130	              (1 << NF_INET_POST_ROUTING),
    131	.me         = THIS_MODULE,
    132};
    133
    134static int __init owner_mt_init(void)
    135{
    136	return xt_register_match(&owner_mt_reg);
    137}
    138
    139static void __exit owner_mt_exit(void)
    140{
    141	xt_unregister_match(&owner_mt_reg);
    142}
    143
    144module_init(owner_mt_init);
    145module_exit(owner_mt_exit);
    146MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
    147MODULE_DESCRIPTION("Xtables: socket owner matching");
    148MODULE_LICENSE("GPL");
    149MODULE_ALIAS("ipt_owner");
    150MODULE_ALIAS("ip6t_owner");