diff options
| author | David S. Miller <davem@davemloft.net> | 2012-08-24 18:54:37 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-08-24 18:54:37 -0400 |
| commit | e6acb384807406c1a6ad3ddc91191f7658e63b7a (patch) | |
| tree | 7906d1bb402ac30e4efaa1bc6451b1c7a4b6e768 /net/netfilter | |
| parent | 255e87657a84e21986e5d9070f3dee4aa8d1d531 (diff) | |
| parent | 898132ae76d1aeb52301f10e8795c34fbb54e853 (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.c | 14 | ||||
| -rw-r--r-- | net/netfilter/xt_LOG.c | 16 | ||||
| -rw-r--r-- | net/netfilter/xt_owner.c | 30 | ||||
| -rw-r--r-- | net/netfilter/xt_recent.c | 13 |
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) | |||
| 132 | static void nfulnl_timer(unsigned long data); | 133 | static void nfulnl_timer(unsigned long data); |
| 133 | 134 | ||
| 134 | static struct nfulnl_instance * | 135 | static struct nfulnl_instance * |
| 135 | instance_create(u_int16_t group_num, int pid) | 136 | instance_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 | ||
| 20 | static 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 | |||
| 20 | static bool | 31 | static bool |
| 21 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | 32 | owner_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); |
