10265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt/*
20265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * Kernel module to match various things tied to sockets associated with
30265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * locally generated outgoing packets.
40265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt *
50265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * (C) 2000 Marc Boucher <marc@mbsi.ca>
60265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt *
7edc26f7aaa23591c779d6d6fc833c0c96fbeb3c0Jan Engelhardt * Copyright © CC Computer Consultants GmbH, 2007 - 2008
80265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt *
90265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * This program is free software; you can redistribute it and/or modify
100265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * it under the terms of the GNU General Public License version 2 as
110265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt * published by the Free Software Foundation.
120265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt */
130265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <linux/module.h>
140265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <linux/skbuff.h>
150265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <linux/file.h>
160265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <net/sock.h>
170265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <linux/netfilter/x_tables.h>
180265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt#include <linux/netfilter/xt_owner.h>
190265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
2026711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biedermanstatic int owner_check(const struct xt_mtchk_param *par)
2126711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman{
2226711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	struct xt_owner_match_info *info = par->matchinfo;
2326711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman
2426711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	/* For now only allow adding matches from the initial user namespace */
2526711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) &&
2626711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	    (current_user_ns() != &init_user_ns))
2726711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		return -EINVAL;
2826711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	return 0;
2926711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman}
3026711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman
310265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardtstatic bool
3262fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtowner_mt(const struct sk_buff *skb, struct xt_action_param *par)
330265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt{
34f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt	const struct xt_owner_match_info *info = par->matchinfo;
350265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	const struct file *filp;
360265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
370265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	if (skb->sk == NULL || skb->sk->sk_socket == NULL)
380265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		return (info->match ^ info->invert) == 0;
390265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	else if (info->match & info->invert & XT_OWNER_SOCKET)
400265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		/*
410265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		 * Socket exists but user wanted ! --socket-exists.
420265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		 * (Single ampersands intended.)
430265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		 */
440265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		return false;
450265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
460265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	filp = skb->sk->sk_socket->file;
470265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	if (filp == NULL)
480265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		return ((info->match ^ info->invert) &
490265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt		       (XT_OWNER_UID | XT_OWNER_GID)) == 0;
500265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
5126711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	if (info->match & XT_OWNER_UID) {
5226711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
5326711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
5426711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
5526711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		     uid_lte(filp->f_cred->fsuid, uid_max)) ^
56edc26f7aaa23591c779d6d6fc833c0c96fbeb3c0Jan Engelhardt		    !(info->invert & XT_OWNER_UID))
570265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt			return false;
5826711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	}
590265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
6026711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	if (info->match & XT_OWNER_GID) {
6126711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
6226711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
6326711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
6426711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman		     gid_lte(filp->f_cred->fsgid, gid_max)) ^
65edc26f7aaa23591c779d6d6fc833c0c96fbeb3c0Jan Engelhardt		    !(info->invert & XT_OWNER_GID))
660265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt			return false;
6726711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	}
680265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
690265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt	return true;
700265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt}
710265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
726461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardtstatic struct xt_match owner_mt_reg __read_mostly = {
736461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.name       = "owner",
746461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.revision   = 1,
756461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.family     = NFPROTO_UNSPEC,
7626711a791effbea125fea4284f4d1c4fa8f7bc73Eric W. Biederman	.checkentry = owner_check,
776461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.match      = owner_mt,
786461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.matchsize  = sizeof(struct xt_owner_match_info),
796461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.hooks      = (1 << NF_INET_LOCAL_OUT) |
806461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	              (1 << NF_INET_POST_ROUTING),
816461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	.me         = THIS_MODULE,
820265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt};
830265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
840265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardtstatic int __init owner_mt_init(void)
850265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt{
866461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	return xt_register_match(&owner_mt_reg);
870265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt}
880265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
890265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardtstatic void __exit owner_mt_exit(void)
900265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt{
916461caed83412ae3e9a16785ffa64396fb66c6a6Jan Engelhardt	xt_unregister_match(&owner_mt_reg);
920265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt}
930265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardt
940265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardtmodule_init(owner_mt_init);
950265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan Engelhardtmodule_exit(owner_mt_exit);
966461caed83412ae3e9a16785ffa64396fb66c6a6Jan EngelhardtMODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
972ae15b64e6a1608c840c60df38e8e5eef7b2b8c3Jan EngelhardtMODULE_DESCRIPTION("Xtables: socket owner matching");
980265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan EngelhardtMODULE_LICENSE("GPL");
990265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan EngelhardtMODULE_ALIAS("ipt_owner");
1000265ab44bacc1a1e0e3f5873d8ca2d5a29e33db2Jan EngelhardtMODULE_ALIAS("ip6t_owner");
101