Add security hooks to allow security modules to exercise access control over GTP. The 'struct gtp_dev' has been moved to include/net/gtp.h so that it is visible to LSM security modules where their security blob is stored. Signed-off-by: Richard Haines <richard_c_haines@xxxxxxxxxxxxxx> --- drivers/net/gtp.c | 50 ++++++++++++++++++++++++++++++++--------------- include/net/gtp.h | 21 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 21640a035..100ee4f9c 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -60,21 +60,6 @@ struct pdp_ctx { struct rcu_head rcu_head; }; -/* One instance of the GTP device. */ -struct gtp_dev { - struct list_head list; - - struct sock *sk0; - struct sock *sk1u; - - struct net_device *dev; - - unsigned int role; - unsigned int hash_size; - struct hlist_head *tid_hash; - struct hlist_head *addr_hash; -}; - static unsigned int gtp_net_id __read_mostly; struct gtp_net { @@ -663,6 +648,10 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); + err = security_gtp_dev_alloc(gtp); + if (err < 0) + return err; + err = gtp_encap_enable(gtp, data); if (err < 0) return err; @@ -705,7 +694,13 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) { struct gtp_dev *gtp = netdev_priv(dev); struct pdp_ctx *pctx; - int i; + int i, err; + + err = security_gtp_dev_free(gtp); + if (err < 0) { + pr_err("Failed security_gtp_dev_free() err: %d\n", err); + return; + } for (i = 0; i < gtp->hash_size; i++) hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) @@ -1076,6 +1071,10 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } + err = security_gtp_dev_cmd(gtp, GTP_CMD_NEWPDP); + if (err < 0) + goto out_unlock; + if (version == GTP_V0) sk = gtp->sk0; else if (version == GTP_V1) @@ -1139,6 +1138,7 @@ static struct pdp_ctx *gtp_find_pdp(struct net *net, struct nlattr *nla[]) static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) { struct pdp_ctx *pctx; + struct gtp_dev *gtp; int err = 0; if (!info->attrs[GTPA_VERSION]) @@ -1152,6 +1152,11 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } + gtp = netdev_priv(pctx->dev); + err = security_gtp_dev_cmd(gtp, GTP_CMD_DELPDP); + if (err < 0) + goto out_unlock; + if (pctx->gtp_version == GTP_V0) netdev_dbg(pctx->dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n", pctx->u.v0.tid, pctx); @@ -1208,6 +1213,7 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info) { struct pdp_ctx *pctx = NULL; struct sk_buff *skb2; + struct gtp_dev *gtp; int err; if (!info->attrs[GTPA_VERSION]) @@ -1221,6 +1227,11 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info) goto err_unlock; } + gtp = netdev_priv(pctx->dev); + err = security_gtp_dev_cmd(gtp, GTP_CMD_GETPDP); + if (err < 0) + goto err_unlock; + skb2 = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (skb2 == NULL) { err = -ENOMEM; @@ -1250,6 +1261,7 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, struct net *net = sock_net(skb->sk); struct pdp_ctx *pctx; struct gtp_net *gn; + int err; gn = net_generic(net, gtp_net_id); @@ -1263,6 +1275,12 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, else last_gtp = NULL; + err = security_gtp_dev_cmd(gtp, GTP_CMD_GETPDP); + if (err < 0) { + rcu_read_unlock(); + return err; + } + for (i = bucket; i < gtp->hash_size; i++) { j = 0; hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], diff --git a/include/net/gtp.h b/include/net/gtp.h index 0e16ebb2a..84b68cf8d 100644 --- a/include/net/gtp.h +++ b/include/net/gtp.h @@ -32,4 +32,25 @@ struct gtp1_header { /* According to 3GPP TS 29.060. */ #define GTP1_F_EXTHDR 0x04 #define GTP1_F_MASK 0x07 +/* + * One instance of the GTP device. + * Any LSM security module can access their security blob here. + */ +struct gtp_dev { + struct list_head list; + + struct sock *sk0; + struct sock *sk1u; + + struct net_device *dev; + + unsigned int role; + unsigned int hash_size; + struct hlist_head *tid_hash; + struct hlist_head *addr_hash; +#ifdef CONFIG_SECURITY + void *security; +#endif +}; + #endif -- 2.26.2