|
@@ -507,7 +507,8 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(__ip_select_ident);
|
|
EXPORT_SYMBOL(__ip_select_ident);
|
|
|
|
|
|
-static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
|
|
|
|
|
|
+static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
|
|
|
|
+ const struct sock *sk,
|
|
const struct iphdr *iph,
|
|
const struct iphdr *iph,
|
|
int oif, u8 tos,
|
|
int oif, u8 tos,
|
|
u8 prot, u32 mark, int flow_flags)
|
|
u8 prot, u32 mark, int flow_flags)
|
|
@@ -523,7 +524,8 @@ static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
|
|
flowi4_init_output(fl4, oif, mark, tos,
|
|
flowi4_init_output(fl4, oif, mark, tos,
|
|
RT_SCOPE_UNIVERSE, prot,
|
|
RT_SCOPE_UNIVERSE, prot,
|
|
flow_flags,
|
|
flow_flags,
|
|
- iph->daddr, iph->saddr, 0, 0);
|
|
|
|
|
|
+ iph->daddr, iph->saddr, 0, 0,
|
|
|
|
+ sock_net_uid(net, sk));
|
|
}
|
|
}
|
|
|
|
|
|
static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
|
|
static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
|
|
@@ -535,7 +537,7 @@ static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
|
|
u8 prot = iph->protocol;
|
|
u8 prot = iph->protocol;
|
|
u32 mark = skb->mark;
|
|
u32 mark = skb->mark;
|
|
|
|
|
|
- __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
|
|
|
|
|
|
+ __build_flow_key(sock_net(sk), fl4, sk, iph, oif, tos, prot, mark, 0);
|
|
}
|
|
}
|
|
|
|
|
|
static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
|
|
static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
|
|
@@ -552,7 +554,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
|
|
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
|
|
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
|
|
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
|
|
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
|
|
inet_sk_flowi_flags(sk),
|
|
inet_sk_flowi_flags(sk),
|
|
- daddr, inet->inet_saddr, 0, 0);
|
|
|
|
|
|
+ daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -800,7 +802,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
|
|
|
|
|
|
rt = (struct rtable *) dst;
|
|
rt = (struct rtable *) dst;
|
|
|
|
|
|
- __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
|
|
|
|
|
|
+ __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
|
|
__ip_do_redirect(rt, skb, &fl4, true);
|
|
__ip_do_redirect(rt, skb, &fl4, true);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1018,7 +1020,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
|
|
if (!mark)
|
|
if (!mark)
|
|
mark = IP4_REPLY_MARK(net, skb->mark);
|
|
mark = IP4_REPLY_MARK(net, skb->mark);
|
|
|
|
|
|
- __build_flow_key(&fl4, NULL, iph, oif,
|
|
|
|
|
|
+ __build_flow_key(net, &fl4, NULL, iph, oif,
|
|
RT_TOS(iph->tos), protocol, mark, flow_flags);
|
|
RT_TOS(iph->tos), protocol, mark, flow_flags);
|
|
rt = __ip_route_output_key(net, &fl4);
|
|
rt = __ip_route_output_key(net, &fl4);
|
|
if (!IS_ERR(rt)) {
|
|
if (!IS_ERR(rt)) {
|
|
@@ -1034,7 +1036,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
|
|
struct flowi4 fl4;
|
|
struct flowi4 fl4;
|
|
struct rtable *rt;
|
|
struct rtable *rt;
|
|
|
|
|
|
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
|
|
+ __build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
|
|
if (!fl4.flowi4_mark)
|
|
if (!fl4.flowi4_mark)
|
|
fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
|
|
fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
|
|
@@ -1053,6 +1055,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
|
|
struct rtable *rt;
|
|
struct rtable *rt;
|
|
struct dst_entry *odst = NULL;
|
|
struct dst_entry *odst = NULL;
|
|
bool new = false;
|
|
bool new = false;
|
|
|
|
+ struct net *net = sock_net(sk);
|
|
|
|
|
|
bh_lock_sock(sk);
|
|
bh_lock_sock(sk);
|
|
|
|
|
|
@@ -1066,7 +1069,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
|
|
+ __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
|
|
rt = (struct rtable *)odst;
|
|
rt = (struct rtable *)odst;
|
|
if (odst->obsolete && !odst->ops->check(odst, 0)) {
|
|
if (odst->obsolete && !odst->ops->check(odst, 0)) {
|
|
@@ -1106,7 +1109,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
|
|
struct flowi4 fl4;
|
|
struct flowi4 fl4;
|
|
struct rtable *rt;
|
|
struct rtable *rt;
|
|
|
|
|
|
- __build_flow_key(&fl4, NULL, iph, oif,
|
|
|
|
|
|
+ __build_flow_key(net, &fl4, NULL, iph, oif,
|
|
RT_TOS(iph->tos), protocol, mark, flow_flags);
|
|
RT_TOS(iph->tos), protocol, mark, flow_flags);
|
|
rt = __ip_route_output_key(net, &fl4);
|
|
rt = __ip_route_output_key(net, &fl4);
|
|
if (!IS_ERR(rt)) {
|
|
if (!IS_ERR(rt)) {
|
|
@@ -1121,9 +1124,10 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
|
|
const struct iphdr *iph = (const struct iphdr *) skb->data;
|
|
const struct iphdr *iph = (const struct iphdr *) skb->data;
|
|
struct flowi4 fl4;
|
|
struct flowi4 fl4;
|
|
struct rtable *rt;
|
|
struct rtable *rt;
|
|
|
|
+ struct net *net = sock_net(sk);
|
|
|
|
|
|
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
- rt = __ip_route_output_key(sock_net(sk), &fl4);
|
|
|
|
|
|
+ __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
|
|
|
|
+ rt = __ip_route_output_key(net, &fl4);
|
|
if (!IS_ERR(rt)) {
|
|
if (!IS_ERR(rt)) {
|
|
__ip_do_redirect(rt, skb, &fl4, false);
|
|
__ip_do_redirect(rt, skb, &fl4, false);
|
|
ip_rt_put(rt);
|
|
ip_rt_put(rt);
|
|
@@ -2504,6 +2508,11 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
|
|
nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))
|
|
nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
+ if (!uid_eq(fl4->flowi4_uid, INVALID_UID) &&
|
|
|
|
+ nla_put_u32(skb, RTA_UID,
|
|
|
|
+ from_kuid_munged(current_user_ns(), fl4->flowi4_uid)))
|
|
|
|
+ goto nla_put_failure;
|
|
|
|
+
|
|
error = rt->dst.error;
|
|
error = rt->dst.error;
|
|
|
|
|
|
if (rt_is_input_route(rt)) {
|
|
if (rt_is_input_route(rt)) {
|
|
@@ -2556,6 +2565,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
|
|
int mark;
|
|
int mark;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
u32 table_id = RT_TABLE_MAIN;
|
|
u32 table_id = RT_TABLE_MAIN;
|
|
|
|
+ kuid_t uid;
|
|
|
|
|
|
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
|
|
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -2583,6 +2593,10 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
|
|
dst = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
|
|
dst = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
|
|
iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
|
|
iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
|
|
mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
|
|
mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
|
|
|
|
+ if (tb[RTA_UID])
|
|
|
|
+ uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID]));
|
|
|
|
+ else
|
|
|
|
+ uid = (iif ? INVALID_UID : current_uid());
|
|
|
|
|
|
memset(&fl4, 0, sizeof(fl4));
|
|
memset(&fl4, 0, sizeof(fl4));
|
|
fl4.daddr = dst;
|
|
fl4.daddr = dst;
|
|
@@ -2590,6 +2604,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
|
|
fl4.flowi4_tos = rtm->rtm_tos;
|
|
fl4.flowi4_tos = rtm->rtm_tos;
|
|
fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
|
|
fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
|
|
fl4.flowi4_mark = mark;
|
|
fl4.flowi4_mark = mark;
|
|
|
|
+ fl4.flowi4_uid = uid;
|
|
|
|
|
|
if (iif) {
|
|
if (iif) {
|
|
struct net_device *dev;
|
|
struct net_device *dev;
|