lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 13 Mar 2017 00:01:27 +0100 From: Hannes Frederic Sowa <hannes@...essinduktion.org> To: netdev@...r.kernel.org Subject: [PATCH net-next RFC v1 03/27] afnetns: prepare for integration into ipv4 Each IPv4 address has an associated afnet namespace, so it is only going to be used by applications in the same afnet namespace. One can open a file descriptor and pass it to the newaddr rtnetlink functions to put an IP address into a specific afnet namespace. Dumping the addresses also returns the appropriate afnetns inode number, so a match with the appropriate afnet namespace can be done in user space. Signed-off-by: Hannes Frederic Sowa <hannes@...essinduktion.org> --- include/linux/inetdevice.h | 3 +++ include/net/afnetns.h | 2 ++ include/uapi/linux/if_addr.h | 2 ++ net/core/afnetns.c | 26 ++++++++++++++++++++++++++ net/ipv4/devinet.c | 39 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index ee971f335a8b65..d5ac959e90baa1 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -141,6 +141,9 @@ struct in_ifaddr { unsigned char ifa_scope; unsigned char ifa_prefixlen; __u32 ifa_flags; +#if IS_ENABLED(CONFIG_AFNETNS) + struct afnetns *afnetns; +#endif char ifa_label[IFNAMSIZ]; /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */ diff --git a/include/net/afnetns.h b/include/net/afnetns.h index d5fbb83023acd6..9039086717c356 100644 --- a/include/net/afnetns.h +++ b/include/net/afnetns.h @@ -19,6 +19,8 @@ int afnet_ns_init(void); struct afnetns *afnetns_new(struct net *net); struct afnetns *copy_afnet_ns(unsigned long flags, struct nsproxy *old); +struct afnetns *afnetns_get_by_fd(int fd); +unsigned int afnetns_to_inode(struct afnetns *afnetns); void afnetns_free(struct afnetns *afnetns); static inline struct afnetns *afnetns_get(struct afnetns *afnetns) diff --git a/include/uapi/linux/if_addr.h b/include/uapi/linux/if_addr.h index 4318ab1635cedf..c67703808584eb 100644 --- a/include/uapi/linux/if_addr.h +++ b/include/uapi/linux/if_addr.h @@ -32,6 +32,8 @@ enum { IFA_CACHEINFO, IFA_MULTICAST, IFA_FLAGS, + IFA_AFNETNS_FD, + IFA_AFNETNS_INODE, __IFA_MAX, }; diff --git a/net/core/afnetns.c b/net/core/afnetns.c index 997623e4dc5078..12b823ae780796 100644 --- a/net/core/afnetns.c +++ b/net/core/afnetns.c @@ -2,6 +2,7 @@ #include <net/net_namespace.h> #include <linux/sched.h> #include <linux/sched/task.h> +#include <linux/file.h> #include <linux/nsproxy.h> #include <linux/proc_ns.h> @@ -56,6 +57,31 @@ void afnetns_free(struct afnetns *afnetns) kfree(afnetns); } +struct afnetns *afnetns_get_by_fd(int fd) +{ + struct file *file; + struct ns_common *ns; + struct afnetns *afnetns; + + file = proc_ns_fget(fd); + if (IS_ERR(file)) + return ERR_CAST(file); + + ns = get_proc_ns(file_inode(file)); + if (ns->ops == &afnetns_operations) + afnetns = afnetns_get(ns_to_afnet(ns)); + else + afnetns = ERR_PTR(-EINVAL); + + fput(file); + return afnetns; +} + +unsigned int afnetns_to_inode(struct afnetns *afnetns) +{ + return afnetns->ns.inum; +} + struct afnetns *copy_afnet_ns(unsigned long flags, struct nsproxy *old) { if (flags & CLONE_NEWNET) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cebedd545e5e28..d4a38b6e9adb79 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -99,6 +99,7 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, [IFA_FLAGS] = { .type = NLA_U32 }, + [IFA_AFNETNS_FD] = { .type = NLA_S32 }, }; #define IN4_ADDR_HSIZE_SHIFT 8 @@ -203,6 +204,9 @@ static void inet_rcu_free_ifa(struct rcu_head *head) struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head); if (ifa->ifa_dev) in_dev_put(ifa->ifa_dev); +#if IS_ENABLED(CONFIG_AFNETNS) + afnetns_put(ifa->afnetns); +#endif kfree(ifa); } @@ -805,6 +809,26 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); +#if IS_ENABLED(CONFIG_AFNETNS) + if (tb[IFA_AFNETNS_FD]) { + int fd = nla_get_s32(tb[IFA_AFNETNS_FD]); + + ifa->afnetns = afnetns_get_by_fd(fd); + if (IS_ERR(ifa->afnetns)) { + err = PTR_ERR(ifa->afnetns); + ifa->afnetns = afnetns_get(net->afnet_ns); + goto errout_free; + } + } else { + ifa->afnetns = afnetns_get(net->afnet_ns); + } +#else + if (tb[IFA_AFNETNS_FD]) { + err = -EOPNOTSUPP; + goto errout_free; + } +#endif + if (tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci; @@ -1089,6 +1113,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ifa->ifa_mask = inet_make_mask(32); } set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); +#if IS_ENABLED(CONFIG_AFNETNS) + ifa->afnetns = afnetns_get(net->afnet_ns); +#endif ret = inet_set_ifa(dev, ifa); break; @@ -1444,6 +1471,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, in_dev_hold(in_dev); ifa->ifa_dev = in_dev; ifa->ifa_scope = RT_SCOPE_HOST; +#if IS_ENABLED(CONFIG_AFNETNS) + ifa->afnetns = afnetns_get(dev_net(dev)->afnet_ns); +#endif memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); @@ -1504,7 +1534,8 @@ static size_t inet_nlmsg_size(void) + nla_total_size(4) /* IFA_BROADCAST */ + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ + nla_total_size(4) /* IFA_FLAGS */ - + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */ + + nla_total_size(sizeof(struct ifa_cacheinfo)) /* IFA_CACHEINFO */ + + nla_total_size(4); /* IFA_AFNETNS_INODE */ } static inline u32 cstamp_delta(unsigned long cstamp) @@ -1577,6 +1608,12 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, preferred, valid)) goto nla_put_failure; +#if IS_ENABLED(CONFIG_AFNETNS) + if (nla_put_u32(skb, IFA_AFNETNS_INODE, + afnetns_to_inode(ifa->afnetns))) + goto nla_put_failure; +#endif + nlmsg_end(skb, nlh); return 0; -- 2.9.3
Powered by blists - more mailing lists