aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-08-24 18:54:37 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-24 18:54:37 -0400
commite6acb384807406c1a6ad3ddc91191f7658e63b7a (patch)
tree7906d1bb402ac30e4efaa1bc6451b1c7a4b6e768 /net/netfilter
parent255e87657a84e21986e5d9070f3dee4aa8d1d531 (diff)
parent898132ae76d1aeb52301f10e8795c34fbb54e853 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
This is an initial merge in of Eric Biederman's work to start adding user namespace support to the networking. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nfnetlink_log.c14
-rw-r--r--net/netfilter/xt_LOG.c16
-rw-r--r--net/netfilter/xt_owner.c30
-rw-r--r--net/netfilter/xt_recent.c13
4 files changed, 55 insertions, 18 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 169ab59ed9d4..4142aac17c3c 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -55,6 +55,7 @@ struct nfulnl_instance {
55 unsigned int qlen; /* number of nlmsgs in skb */ 55 unsigned int qlen; /* number of nlmsgs in skb */
56 struct sk_buff *skb; /* pre-allocatd skb */ 56 struct sk_buff *skb; /* pre-allocatd skb */
57 struct timer_list timer; 57 struct timer_list timer;
58 struct user_namespace *peer_user_ns; /* User namespace of the peer process */
58 int peer_pid; /* PID of the peer process */ 59 int peer_pid; /* PID of the peer process */
59 60
60 /* configurable parameters */ 61 /* configurable parameters */
@@ -132,7 +133,7 @@ instance_put(struct nfulnl_instance *inst)
132static void nfulnl_timer(unsigned long data); 133static void nfulnl_timer(unsigned long data);
133 134
134static struct nfulnl_instance * 135static struct nfulnl_instance *
135instance_create(u_int16_t group_num, int pid) 136instance_create(u_int16_t group_num, int pid, struct user_namespace *user_ns)
136{ 137{
137 struct nfulnl_instance *inst; 138 struct nfulnl_instance *inst;
138 int err; 139 int err;
@@ -162,6 +163,7 @@ instance_create(u_int16_t group_num, int pid)
162 163
163 setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); 164 setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
164 165
166 inst->peer_user_ns = user_ns;
165 inst->peer_pid = pid; 167 inst->peer_pid = pid;
166 inst->group_num = group_num; 168 inst->group_num = group_num;
167 169
@@ -503,8 +505,11 @@ __build_packet_message(struct nfulnl_instance *inst,
503 read_lock_bh(&skb->sk->sk_callback_lock); 505 read_lock_bh(&skb->sk->sk_callback_lock);
504 if (skb->sk->sk_socket && skb->sk->sk_socket->file) { 506 if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
505 struct file *file = skb->sk->sk_socket->file; 507 struct file *file = skb->sk->sk_socket->file;
506 __be32 uid = htonl(file->f_cred->fsuid); 508 __be32 uid = htonl(from_kuid_munged(inst->peer_user_ns,
507 __be32 gid = htonl(file->f_cred->fsgid); 509 file->f_cred->fsuid));
510 __be32 gid = htonl(from_kgid_munged(inst->peer_user_ns,
511 file->f_cred->fsgid));
512 /* need to unlock here since NLA_PUT may goto */
508 read_unlock_bh(&skb->sk->sk_callback_lock); 513 read_unlock_bh(&skb->sk->sk_callback_lock);
509 if (nla_put_be32(inst->skb, NFULA_UID, uid) || 514 if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
510 nla_put_be32(inst->skb, NFULA_GID, gid)) 515 nla_put_be32(inst->skb, NFULA_GID, gid))
@@ -783,7 +788,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
783 } 788 }
784 789
785 inst = instance_create(group_num, 790 inst = instance_create(group_num,
786 NETLINK_CB(skb).pid); 791 NETLINK_CB(skb).pid,
792 sk_user_ns(NETLINK_CB(skb).ssk));
787 if (IS_ERR(inst)) { 793 if (IS_ERR(inst)) {
788 ret = PTR_ERR(inst); 794 ret = PTR_ERR(inst);
789 goto out; 795 goto out;
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index ff5f75fddb15..02a2bf49dcbd 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -363,10 +363,12 @@ static void dump_ipv4_packet(struct sbuff *m,
363 /* Max length: 15 "UID=4294967295 " */ 363 /* Max length: 15 "UID=4294967295 " */
364 if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { 364 if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) {
365 read_lock_bh(&skb->sk->sk_callback_lock); 365 read_lock_bh(&skb->sk->sk_callback_lock);
366 if (skb->sk->sk_socket && skb->sk->sk_socket->file) 366 if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
367 const struct cred *cred = skb->sk->sk_socket->file->f_cred;
367 sb_add(m, "UID=%u GID=%u ", 368 sb_add(m, "UID=%u GID=%u ",
368 skb->sk->sk_socket->file->f_cred->fsuid, 369 from_kuid_munged(&init_user_ns, cred->fsuid),
369 skb->sk->sk_socket->file->f_cred->fsgid); 370 from_kgid_munged(&init_user_ns, cred->fsgid));
371 }
370 read_unlock_bh(&skb->sk->sk_callback_lock); 372 read_unlock_bh(&skb->sk->sk_callback_lock);
371 } 373 }
372 374
@@ -719,10 +721,12 @@ static void dump_ipv6_packet(struct sbuff *m,
719 /* Max length: 15 "UID=4294967295 " */ 721 /* Max length: 15 "UID=4294967295 " */
720 if ((logflags & XT_LOG_UID) && recurse && skb->sk) { 722 if ((logflags & XT_LOG_UID) && recurse && skb->sk) {
721 read_lock_bh(&skb->sk->sk_callback_lock); 723 read_lock_bh(&skb->sk->sk_callback_lock);
722 if (skb->sk->sk_socket && skb->sk->sk_socket->file) 724 if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
725 const struct cred *cred = skb->sk->sk_socket->file->f_cred;
723 sb_add(m, "UID=%u GID=%u ", 726 sb_add(m, "UID=%u GID=%u ",
724 skb->sk->sk_socket->file->f_cred->fsuid, 727 from_kuid_munged(&init_user_ns, cred->fsuid),
725 skb->sk->sk_socket->file->f_cred->fsgid); 728 from_kgid_munged(&init_user_ns, cred->fsgid));
729 }
726 read_unlock_bh(&skb->sk->sk_callback_lock); 730 read_unlock_bh(&skb->sk->sk_callback_lock);
727 } 731 }
728 732
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
index 772d7389b337..ca2e577ed8ac 100644
--- a/net/netfilter/xt_owner.c
+++ b/net/netfilter/xt_owner.c
@@ -17,6 +17,17 @@
17#include <linux/netfilter/x_tables.h> 17#include <linux/netfilter/x_tables.h>
18#include <linux/netfilter/xt_owner.h> 18#include <linux/netfilter/xt_owner.h>
19 19
20static int owner_check(const struct xt_mtchk_param *par)
21{
22 struct xt_owner_match_info *info = par->matchinfo;
23
24 /* For now only allow adding matches from the initial user namespace */
25 if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) &&
26 (current_user_ns() != &init_user_ns))
27 return -EINVAL;
28 return 0;
29}
30
20static bool 31static bool
21owner_mt(const struct sk_buff *skb, struct xt_action_param *par) 32owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
22{ 33{
@@ -37,17 +48,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
37 return ((info->match ^ info->invert) & 48 return ((info->match ^ info->invert) &
38 (XT_OWNER_UID | XT_OWNER_GID)) == 0; 49 (XT_OWNER_UID | XT_OWNER_GID)) == 0;
39 50
40 if (info->match & XT_OWNER_UID) 51 if (info->match & XT_OWNER_UID) {
41 if ((filp->f_cred->fsuid >= info->uid_min && 52 kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
42 filp->f_cred->fsuid <= info->uid_max) ^ 53 kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
54 if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
55 uid_lte(filp->f_cred->fsuid, uid_max)) ^
43 !(info->invert & XT_OWNER_UID)) 56 !(info->invert & XT_OWNER_UID))
44 return false; 57 return false;
58 }
45 59
46 if (info->match & XT_OWNER_GID) 60 if (info->match & XT_OWNER_GID) {
47 if ((filp->f_cred->fsgid >= info->gid_min && 61 kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
48 filp->f_cred->fsgid <= info->gid_max) ^ 62 kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
63 if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
64 gid_lte(filp->f_cred->fsgid, gid_max)) ^
49 !(info->invert & XT_OWNER_GID)) 65 !(info->invert & XT_OWNER_GID))
50 return false; 66 return false;
67 }
51 68
52 return true; 69 return true;
53} 70}
@@ -56,6 +73,7 @@ static struct xt_match owner_mt_reg __read_mostly = {
56 .name = "owner", 73 .name = "owner",
57 .revision = 1, 74 .revision = 1,
58 .family = NFPROTO_UNSPEC, 75 .family = NFPROTO_UNSPEC,
76 .checkentry = owner_check,
59 .match = owner_mt, 77 .match = owner_mt,
60 .matchsize = sizeof(struct xt_owner_match_info), 78 .matchsize = sizeof(struct xt_owner_match_info),
61 .hooks = (1 << NF_INET_LOCAL_OUT) | 79 .hooks = (1 << NF_INET_LOCAL_OUT) |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index ae2ad1eec8d0..4635c9b00459 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -317,6 +317,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
317 struct recent_table *t; 317 struct recent_table *t;
318#ifdef CONFIG_PROC_FS 318#ifdef CONFIG_PROC_FS
319 struct proc_dir_entry *pde; 319 struct proc_dir_entry *pde;
320 kuid_t uid;
321 kgid_t gid;
320#endif 322#endif
321 unsigned int i; 323 unsigned int i;
322 int ret = -EINVAL; 324 int ret = -EINVAL;
@@ -372,6 +374,13 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
372 for (i = 0; i < ip_list_hash_size; i++) 374 for (i = 0; i < ip_list_hash_size; i++)
373 INIT_LIST_HEAD(&t->iphash[i]); 375 INIT_LIST_HEAD(&t->iphash[i]);
374#ifdef CONFIG_PROC_FS 376#ifdef CONFIG_PROC_FS
377 uid = make_kuid(&init_user_ns, ip_list_uid);
378 gid = make_kgid(&init_user_ns, ip_list_gid);
379 if (!uid_valid(uid) || !gid_valid(gid)) {
380 kfree(t);
381 ret = -EINVAL;
382 goto out;
383 }
375 pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, 384 pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
376 &recent_mt_fops, t); 385 &recent_mt_fops, t);
377 if (pde == NULL) { 386 if (pde == NULL) {
@@ -379,8 +388,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
379 ret = -ENOMEM; 388 ret = -ENOMEM;
380 goto out; 389 goto out;
381 } 390 }
382 pde->uid = ip_list_uid; 391 pde->uid = uid;
383 pde->gid = ip_list_gid; 392 pde->gid = gid;
384#endif 393#endif
385 spin_lock_bh(&recent_lock); 394 spin_lock_bh(&recent_lock);
386 list_add_tail(&t->list, &recent_net->tables); 395 list_add_tail(&t->list, &recent_net->tables);