Skip to content

Commit 4f82f45

Browse files
committed
net ip6 flowlabel: Make owner a union of struct pid * and kuid_t
Correct a long standing omission and use struct pid in the owner field of struct ip6_flowlabel when the share type is IPV6_FL_S_PROCESS. This guarantees we don't have issues when pid wraparound occurs. Use a kuid_t in the owner field of struct ip6_flowlabel when the share type is IPV6_FL_S_USER to add user namespace support. In /proc/net/ip6_flowlabel capture the current pid namespace when opening the file and release the pid namespace when the file is closed ensuring we print the pid owner value that is meaning to the reader of the file. Similarly use from_kuid_munged to print uid values that are meaningful to the reader of the file. This requires exporting pid_nr_ns so that ipv6 can continue to built as a module. Yoiks what silliness Acked-by: David S. Miller <[email protected]> Acked-by: Serge Hallyn <[email protected]> Signed-off-by: Eric W. Biederman <[email protected]>
1 parent 7064d16 commit 4f82f45

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

include/net/ipv6.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,10 @@ struct ip6_flowlabel {
222222
struct ipv6_txoptions *opt;
223223
unsigned long linger;
224224
u8 share;
225-
u32 owner;
225+
union {
226+
struct pid *pid;
227+
kuid_t uid;
228+
} owner;
226229
unsigned long lastuse;
227230
unsigned long expires;
228231
struct net *fl_net;

init/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,6 @@ config UIDGID_CONVERTED
948948
depends on NETFILTER_XT_MATCH_RECENT = n
949949
depends on NETFILTER_XT_TARGET_LOG = n
950950
depends on NETFILTER_NETLINK_LOG = n
951-
depends on IPV6 = n
952951
depends on AF_RXRPC = n
953952
depends on NET_KEY = n
954953
depends on INET_DIAG = n

kernel/pid.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
479479
}
480480
return nr;
481481
}
482+
EXPORT_SYMBOL_GPL(pid_nr_ns);
482483

483484
pid_t pid_vnr(struct pid *pid)
484485
{

net/ipv6/ip6_flowlabel.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/seq_file.h>
2323
#include <linux/slab.h>
2424
#include <linux/export.h>
25+
#include <linux/pid_namespace.h>
2526

2627
#include <net/net_namespace.h>
2728
#include <net/sock.h>
@@ -90,6 +91,11 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
9091

9192
static void fl_free(struct ip6_flowlabel *fl)
9293
{
94+
switch (fl->share) {
95+
case IPV6_FL_S_PROCESS:
96+
put_pid(fl->owner.pid);
97+
break;
98+
}
9399
if (fl) {
94100
release_net(fl->fl_net);
95101
kfree(fl->opt);
@@ -394,10 +400,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
394400
case IPV6_FL_S_ANY:
395401
break;
396402
case IPV6_FL_S_PROCESS:
397-
fl->owner = current->pid;
403+
fl->owner.pid = get_task_pid(current, PIDTYPE_PID);
398404
break;
399405
case IPV6_FL_S_USER:
400-
fl->owner = current_euid();
406+
fl->owner.uid = current_euid();
401407
break;
402408
default:
403409
err = -EINVAL;
@@ -561,7 +567,10 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
561567
err = -EPERM;
562568
if (fl1->share == IPV6_FL_S_EXCL ||
563569
fl1->share != fl->share ||
564-
fl1->owner != fl->owner)
570+
((fl1->share == IPV6_FL_S_PROCESS) &&
571+
(fl1->owner.pid == fl->owner.pid)) ||
572+
((fl1->share == IPV6_FL_S_USER) &&
573+
uid_eq(fl1->owner.uid, fl->owner.uid)))
565574
goto release;
566575

567576
err = -EINVAL;
@@ -621,6 +630,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
621630

622631
struct ip6fl_iter_state {
623632
struct seq_net_private p;
633+
struct pid_namespace *pid_ns;
624634
int bucket;
625635
};
626636

@@ -699,6 +709,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
699709

700710
static int ip6fl_seq_show(struct seq_file *seq, void *v)
701711
{
712+
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
702713
if (v == SEQ_START_TOKEN)
703714
seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
704715
"Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
@@ -708,7 +719,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
708719
"%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
709720
(unsigned int)ntohl(fl->label),
710721
fl->share,
711-
(int)fl->owner,
722+
((fl->share == IPV6_FL_S_PROCESS) ?
723+
pid_nr_ns(fl->owner.pid, state->pid_ns) :
724+
((fl->share == IPV6_FL_S_USER) ?
725+
from_kuid_munged(seq_user_ns(seq), fl->owner.uid) :
726+
0)),
712727
atomic_read(&fl->users),
713728
fl->linger/HZ,
714729
(long)(fl->expires - jiffies)/HZ,
@@ -727,16 +742,37 @@ static const struct seq_operations ip6fl_seq_ops = {
727742

728743
static int ip6fl_seq_open(struct inode *inode, struct file *file)
729744
{
730-
return seq_open_net(inode, file, &ip6fl_seq_ops,
731-
sizeof(struct ip6fl_iter_state));
745+
struct seq_file *seq;
746+
struct ip6fl_iter_state *state;
747+
int err;
748+
749+
err = seq_open_net(inode, file, &ip6fl_seq_ops,
750+
sizeof(struct ip6fl_iter_state));
751+
752+
if (!err) {
753+
seq = file->private_data;
754+
state = ip6fl_seq_private(seq);
755+
rcu_read_lock();
756+
state->pid_ns = get_pid_ns(task_active_pid_ns(current));
757+
rcu_read_unlock();
758+
}
759+
return err;
760+
}
761+
762+
static int ip6fl_seq_release(struct inode *inode, struct file *file)
763+
{
764+
struct seq_file *seq = file->private_data;
765+
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
766+
put_pid_ns(state->pid_ns);
767+
return seq_release_net(inode, file);
732768
}
733769

734770
static const struct file_operations ip6fl_seq_fops = {
735771
.owner = THIS_MODULE,
736772
.open = ip6fl_seq_open,
737773
.read = seq_read,
738774
.llseek = seq_lseek,
739-
.release = seq_release_net,
775+
.release = ip6fl_seq_release,
740776
};
741777

742778
static int __net_init ip6_flowlabel_proc_init(struct net *net)

0 commit comments

Comments
 (0)