Message ID | 20200930094934.32144-4-richard_c_haines@btinternet.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Paul Moore |
Headers | show |
Series | Add LSM/SELinux support for GPRS Tunneling Protocol (GTP) | expand |
Hi Richard, I don't fully understand in which context you need / use those SELinux GTP hooks, however one comment from the point of view of somebody who is working on GGSN/P-GW software using the GTP kernel module: On Wed, Sep 30, 2020 at 10:49:34AM +0100, Richard Haines wrote: > +selinux_gtp_dev_cmd() > +~~~~~~~~~~~~~~~~~~~~~ > +Validate if the caller (current SID) and the GTP device SID have the required > +permission to perform the operation. The GTP/SELinux permission map is > +as follow:: > + > + GTP_CMD_NEWPDP = gtp { add } > + GTP_CMD_DELPDP = gtp { del } > + GTP_CMD_GETPDP = gtp { get } Wouldn't it make sense to differentiate between: a) add/del/get on the GTP netdev b) add/del/get on the indivudual PDP wihin the GTP netdev 'a' is typically only created once at startup of a GGSN/P-GW software, or is done even at system stat-up time. 'b' is performed frequently during runtime as the GGSN/P-GW function runs, as subscribers attach to / detach from the cellular network. By differentiating between those two, one could further constrain the permissions required at runtime.
On Wed, 2020-09-30 at 13:01 +0200, Harald Welte wrote: > Hi Richard, > > I don't fully understand in which context you need / use those > SELinux GTP hooks, As in the reply to Pablo, I did it for no particular reason other than idle curiosity, and given the attempted move to Open 5G I thought adding MAC support might be useful somewhere along the line. > however one comment from the point of view of somebody who is working > on GGSN/P-GW > software using the GTP kernel module: > > On Wed, Sep 30, 2020 at 10:49:34AM +0100, Richard Haines wrote: > > +selinux_gtp_dev_cmd() > > +~~~~~~~~~~~~~~~~~~~~~ > > +Validate if the caller (current SID) and the GTP device SID have > > the required > > +permission to perform the operation. The GTP/SELinux permission > > map is > > +as follow:: > > + > > + GTP_CMD_NEWPDP = gtp { add } > > + GTP_CMD_DELPDP = gtp { del } > > + GTP_CMD_GETPDP = gtp { get } > > Wouldn't it make sense to differentiate between: > > a) add/del/get on the GTP netdev > b) add/del/get on the indivudual PDP wihin the GTP netdev > > 'a' is typically only created once at startup of a GGSN/P-GW > software, or is > done even at system stat-up time. > > 'b' is performed frequently during runtime as the GGSN/P-GW function > runs, as > subscribers attach to / detach from the cellular network. > > By differentiating between those two, one could further constrain the > permissions > required at runtime. Yes, at first I did separate them (add_dev, del_dev, add_pkt, del_pkt, get_pkt), so if this patchset goes anywhere then I can change it no problem. I guess the '*_pkt' permissions would cover PDP for 3G and PDR & FAR for 5G ?. I didn't implement 'get_dev' but thought it could be useful for retrieving the security context of a device, but that requires passing it back via netlink so thought I would leave it until later. >
Hi Richard, On Wed, Sep 30, 2020 at 01:25:27PM +0100, Richard Haines wrote: > As in the reply to Pablo, I did it for no particular reason other than > idle curiosity, and given the attempted move to Open 5G I thought > adding MAC support might be useful somewhere along the line. thanks, I only saw your related mail earlier today. Unfortunately there's a lot of talk about "open source" in the context of 5G but as far as I can tell (and I'm involved in open source cellular full-time for a decade now) it's mostly marketing. And if something is relased, it's some shared source license that doesn't pass the OSI OSD nor DFSG, ... In any case, this is off-topic here. I think it would not be the best idea to merge SELinux support patches for the GTP kernel driver without thoroughly understanding the use case, and/or having some actual userspace implementations that make use of them. In the end, we may be introducing code that nobody uses, and which only turns out to be insufficient for what later actual users may want. So like Pablo suggested, it would probably be best to focus on submitting / merging features for things that are either well-defined (e.g. specified in a standerd), and/or have existing userspace implementations. > I guess the '*_pkt' permissions would cover PDP for 3G and PDR > & FAR for 5G ?. The permissions would probably cover those two items, yes. As you probably know, we currently don't have any ability in the kernel GTP driver to map "external" IP traffic to TEID based on anything except the destination IP address. This is sufficient for all 2G and 3G use cases, and should also cover many 4G use cases. However, if you want to go for different dedicated bearers and QoS classes, for sure you need something more advanced in terms of classification of packets. Regards, Harald
On Wed, Sep 30, 2020 at 9:39 AM Harald Welte <laforge@gnumonks.org> wrote: > Hi Richard, > > On Wed, Sep 30, 2020 at 01:25:27PM +0100, Richard Haines wrote: > > > As in the reply to Pablo, I did it for no particular reason other than > > idle curiosity, and given the attempted move to Open 5G I thought > > adding MAC support might be useful somewhere along the line. > > ... > > I think it would not be the best idea to merge SELinux support patches for the > GTP kernel driver without thoroughly understanding the use case, and/or having > some actual userspace implementations that make use of them. In the end, we may > be introducing code that nobody uses, and which only turns out to be insufficient > for what later actual users may want. > > So like Pablo suggested, it would probably be best to focus on > submitting / merging features for things that are either well-defined (e.g. > specified in a standerd), and/or have existing userspace implementations. Having a solid use case or two is also helpful for those of us who don't have a GTP/GPRS background. I did spend some time reading a few things on GTP, but I don't feel like I've made much of a dent on understanding how it is actually used. Harald, Pablo - I know you both suggested taking a slow iterative approach to merging functionality, perhaps you could also help those of us on the SELinux side better understand some of the common GTP use cases?
Hi Paul, On Sun, Oct 11, 2020 at 10:09:11PM -0400, Paul Moore wrote: > Harald, Pablo - I know you both suggested taking a slow iterative > approach to merging functionality, perhaps you could also help those > of us on the SELinux side better understand some of the common GTP use > cases? There really only is one use case for this code: The GGSN or P-GW function in the 3GPP network architecture. There are open source implementations like OsmoGGSN and (at least older/previos versions) of ergw, but also non-FOSS-but-shared-source (like OpenAirInterface) and proprietary software that use the existing kernel GTP for that. In a GGSN (2G/3G) or P-GW (4G), you have a control plane instance talking a control plane protocol GTP-C (GTPv1-C or GTPv2-C) with other elements in the network, such as the SGSN (2G/3G) or S-GW (4G) This control plane instance will then talk to the user plane instance (which is, in the case of the kernel GTP module, netlink) to crate PDP contexts (2G/3G) or "barers" (4G). Those PDP contexts / bearers are constantly being created, modified and torn down. Creation happens at the time your modern phone attaches to the network (once you have "mobile data" enabled). Modification happens when you start roaming around the country / coverage area as you change between larger regions. Deletion happens once you disable "mobile data' or go into airplane mode. The kernel GTP "tun" device typically represents an "APN", i.e. one specific IP network your phones/modems want to attach to. There could be multiple in parallel (e.g. public internet, private operator network for VoLTE, company-private networks). So you have one tun device per APN which is mostly static configuration, stable for months, years, ... and then you have the hightly volatile PDP contexts / bearers within each of those APN. That's why I was hinting from a security policy point of view, it makes sense to separate those two, as one only happens at system boot / application start time, and the other happens at any point during runtime of your GGSN/PGW. If you want to see how that looks on the wire, check the OsmoGGSN automatic test suite, where every test case generates a pcap file: overview at https://jenkins.osmocom.org/jenkins/view/TTCN3/job/ttcn3-ggsn-test/ actual artefacts including per-test pcap files: https://jenkins.osmocom.org/jenkins/view/TTCN3/job/ttcn3-ggsn-test/lastSuccessfulBuild/artifact/logs/ggsn-tester/ specifically, if you open https://jenkins.osmocom.org/jenkins/view/TTCN3/job/ttcn3-ggsn-test/lastSuccessfulBuild/artifact/logs/ggsn-tester/GGSN_Tests.TC_pdp6_act_deact_gtpu_access.pcap.gz in wirehark and filter on 'gtp', you will see the GTP-C traffic on udp port 2123, and the GTP-U traffic on UDP port 2152. This second part is where you would use the kernel-GTP-U implementation to avoid the kernel-userspace-kernel roundtrip for every user IP packet. There are many other use cases for GTP in general in other network elements such as a S-GW (which basically acts as a proxy for GTP-U), but those are not implemented in the existing Linux kernel GTP module. I think OsmoGGSN is about the most simple to understand user out there, due to its very limited code size. Check https://git.osmocom.org/osmo-ggsn/tree/lib/gtp-kernel.c for the libgtpnl interface and https://git.osmocom.org/osmo-ggsn/tree/ggsn/ggsn.c for the hearth of the logic, including the calls to the gtp_kernel_tunnel_*() API. Hope this helps, Harald
On Mon, Oct 12, 2020 at 5:40 AM Harald Welte <laforge@gnumonks.org> wrote: > > Hi Paul, > > On Sun, Oct 11, 2020 at 10:09:11PM -0400, Paul Moore wrote: > > Harald, Pablo - I know you both suggested taking a slow iterative > > approach to merging functionality, perhaps you could also help those > > of us on the SELinux side better understand some of the common GTP use > > cases? > > There really only is one use case for this code: The GGSN or P-GW function > in the 3GPP network architecture ... > > Hope this helps, > Harald It does, thank you. It looks like this patchset is not really a candidate for merging in its current form, but I didn't want to lose this information (both the patches and Harald's comments) so I created a GH issue to track this at the URL below. * https://github.com/SELinuxProject/selinux-kernel/issues/54
On Tue, 2020-10-13 at 09:55 -0400, Paul Moore wrote: > On Mon, Oct 12, 2020 at 5:40 AM Harald Welte <laforge@gnumonks.org> > wrote: > > Hi Paul, > > > > On Sun, Oct 11, 2020 at 10:09:11PM -0400, Paul Moore wrote: > > > Harald, Pablo - I know you both suggested taking a slow iterative > > > approach to merging functionality, perhaps you could also help > > > those > > > of us on the SELinux side better understand some of the common > > > GTP use > > > cases? > > > > There really only is one use case for this code: The GGSN or P-GW > > function > > in the 3GPP network architecture ... > > > > Hope this helps, > > Harald > > It does, thank you. > > It looks like this patchset is not really a candidate for merging in > its current form, but I didn't want to lose this information (both > the > patches and Harald's comments) so I created a GH issue to track this > at the URL below. > > * https://github.com/SELinuxProject/selinux-kernel/issues/54 > While I was not expecting these patches to be excepted for the current version, the main aim was to see what LSM security services could be implemented on possible 5G components, bearing in mind the DARPA Open Programmable Secure 5G (OPS-5G) initiative (probably 'jumping the gun' here a bit though). There is in development a 5G version of GTP at [1]. I have added the enhanced hooks to this (plus retrieve contexts via call-backs etc.), and have it running on 5.9, passing their tests. I'm not sure how far this development will go, but a starter ??. The other component that seems to be widely used in these systems is SCTP that I added hooks to a few years ago, also TCP/UDP etc. that are already well catered for. Also there would be a large amount of userspace code .... Anyway food for thought. [1] https://github.com/PrinzOwO/gtp5g
Hi Richard and list[s], On Tue, Oct 13, 2020 at 05:38:16PM +0100, Richard Haines wrote: > There is in development a 5G version of GTP at [1]. Please note that there is no such thing as "5G version of GTP". The GTP-U (user plane) did not change between 2G, 3G, 4G or even 5G: IT is still the same protocol version (GTPv1-U), which you can see from looking at 3GPP TS 29.281 even in its latest release (Rel 15), which is what the authors of the "gtp5g" github repository reference. What has changed over time is how the protocol is used, and what kind of QoS/classification features are added in order to use different GTP tunnels for different traffic (to the same subscriber / IP address) in order to subject it to different QoS within the 3GPP network. This functionality, by the way, can also be used in 4G networks, and even in 3G/2G networks that follow some of the later releases. The "gtp5g" module hence should in my point not be a separate module, but it should be broken down in incremental feature enhancements to the existing in-kernel GTP user plane module. The netlink interface should also obviously be extended in a backwards-compatible way. My most active kernel years are long gone, but I still think we never have two implementations of the same protocol (GTPv1U in this case) in the Kernel. One could of course also consider to switch to a completely new implementation / rewrite, but only if it is backwards compatible in terms of use cases as well as the netlink interface (and hence existing users of the GTPv1U kernel support). > The other component that seems to be widely used in these systems is > SCTP that I added hooks to a few years ago, [...] indeed, SCTP is extremely heavily used in all cellular systems, from 2G to 4G (with a peak in 4G), but still used on some 5G interfaces. Unfortunately it is the tradition (until today) that none of the industry players that need and use those protocols (GTP, SCTP) seem to be participating in the development and maintenance effort of related implementation. So rather than Nokia, Ericsson or others improving the in-kernel SCTP, their Linux based devices tend to roll their own [userspace] SCTP implementations. Even while in 2020 everybody in "marketing land" speaks about "open source" in the context of cellular/5G, it is not happening. It is only open-washing in order to appear attractive. In reality, anyone in this industry derives a *massive* revenue from their patent royalty collection and they would do anything but release or contribute to code that comes with an explicit or implicit patent license grant. So here we are, in 2020, where every single cellular equipment maker uses Linux, but the most relevant real open source projects in the industry are run by small enthusiast or very small players... Regards, Harald
diff --git a/Documentation/security/GTP.rst b/Documentation/security/GTP.rst index c748587ec..433fcb688 100644 --- a/Documentation/security/GTP.rst +++ b/Documentation/security/GTP.rst @@ -15,6 +15,9 @@ For security module support, three GTP specific hooks have been implemented:: security_gtp_dev_free() security_gtp_dev_cmd() +The usage of these hooks are described below with the SELinux implementation +described in the `GTP SELinux Support`_ chapter. + security_gtp_dev_alloc() ~~~~~~~~~~~~~~~~~~~~~~ @@ -37,3 +40,61 @@ zero on success, negative values on failure. The commands are based on values from ``include/uapi/linux/gtp.h`` as follows:: ``enum gtp_genl_cmds { GTP_CMD_NEWPDP, GTP_CMD_DELPDP, GTP_CMD_GETPDP };`` + + +GTP SELinux Support +=================== + +Policy Statements +----------------- +The following class and permissions to support GTP are available within the +kernel:: + + class gtp { add del get } + +The permissions are described in the sections that follow. + + +Security Hooks +-------------- + +The `GTP LSM Support`_ chapter above describes the following GTP security +hooks with the SELinux specifics expanded below:: + + security_gtp_dev_alloc -> selinux_gtp_dev_alloc_security(gtp) + security_gtp_dev_free -> selinux_gtp_dev_free_security(gtp) + security_gtp_dev_cmd -> selinux_gtp_dev_cmd(gtp, cmd) + + +selinux_gtp_dev_alloc_security() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allocates a security structure for a GTP device provided the caller has the +``gtp { add }`` permission. Can return errors ``-ENOMEM`` or ``-EACCES``. +Returns zero if the security structure has been allocated. + + +selinux_gtp_dev_free_security() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Frees a security structure for a GTP device provided the caller has the +``gtp { del }`` permission. Can return error ``-EACCES``. Returns zero if the +security structure has been freed. + + +selinux_gtp_dev_cmd() +~~~~~~~~~~~~~~~~~~~~~ +Validate if the caller (current SID) and the GTP device SID have the required +permission to perform the operation. The GTP/SELinux permission map is +as follow:: + + GTP_CMD_NEWPDP = gtp { add } + GTP_CMD_DELPDP = gtp { del } + GTP_CMD_GETPDP = gtp { get } + +Returns ``-EACCES`` if denied or zero if allowed. + +NOTES:: + 1) If the GTP device has the ``{ add }`` permission it can add device and + also add PDP's (packet data protocol). + + 2) If the GTP device has the ``{ del }`` permission it can delete a device + and also delete PDP's. diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d6b182c11..5229a4f20 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -91,6 +91,7 @@ #include <uapi/linux/mount.h> #include <linux/fsnotify.h> #include <linux/fanotify.h> +#include <net/gtp.h> #include "avc.h" #include "objsec.h" @@ -5520,6 +5521,68 @@ static int selinux_tun_dev_open(void *security) return 0; } +static int selinux_gtp_dev_alloc_security(struct gtp_dev *gtp) +{ + struct gtp_security_struct *gtpsec; + u32 sid = current_sid(); + int err; + + err = avc_has_perm(&selinux_state, sid, sid, + SECCLASS_GTP, GTP__ADD, NULL); + if (err < 0) + return err; + + gtpsec = kzalloc(sizeof(*gtpsec), GFP_KERNEL); + if (!gtpsec) + return -ENOMEM; + + gtpsec->sid = sid; + gtp->security = gtpsec; + + return 0; +} + +static int selinux_gtp_dev_free_security(struct gtp_dev *gtp) +{ + struct gtp_security_struct *gtpsec = gtp->security; + u32 sid = current_sid(); + int err; + + err = avc_has_perm(&selinux_state, sid, gtpsec->sid, + SECCLASS_GTP, GTP__DEL, NULL); + if (err < 0) + return err; + + gtp->security = NULL; + kfree(gtpsec); + + return 0; +} + +static int selinux_gtp_dev_cmd(struct gtp_dev *gtp, enum gtp_genl_cmds cmd) +{ + struct gtp_security_struct *gtpsec = gtp->security; + u32 perm, sid = current_sid(); + + switch (cmd) { + case GTP_CMD_NEWPDP: + perm = GTP__ADD; + break; + case GTP_CMD_DELPDP: + perm = GTP__DEL; + break; + case GTP_CMD_GETPDP: + perm = GTP__GET; + break; + default: + WARN_ON(1); + return -EPERM; + } + + return avc_has_perm(&selinux_state, sid, gtpsec->sid, + SECCLASS_GTP, perm, NULL); +} + #ifdef CONFIG_NETFILTER static unsigned int selinux_ip_forward(struct sk_buff *skb, @@ -7130,6 +7193,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue), LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach), LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open), + LSM_HOOK_INIT(gtp_dev_free_security, selinux_gtp_dev_free_security), + LSM_HOOK_INIT(gtp_dev_cmd, selinux_gtp_dev_cmd), #ifdef CONFIG_SECURITY_INFINIBAND LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access), LSM_HOOK_INIT(ib_endport_manage_subnet, @@ -7204,6 +7269,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx), LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security), LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security), + LSM_HOOK_INIT(gtp_dev_alloc_security, selinux_gtp_dev_alloc_security), #ifdef CONFIG_SECURITY_INFINIBAND LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security), #endif diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 40cebde62..3865a4549 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -249,6 +249,8 @@ struct security_class_mapping secclass_map[] = { {"open", "cpu", "kernel", "tracepoint", "read", "write"} }, { "lockdown", { "integrity", "confidentiality", NULL } }, + { "gtp", + { "add", "del", "get", NULL } }, { NULL } }; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 330b7b6d4..311ffb6ea 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -148,6 +148,10 @@ struct perf_event_security_struct { u32 sid; /* SID of perf_event obj creator */ }; +struct gtp_security_struct { + u32 sid; /* SID of gtp obj creator */ +}; + extern struct lsm_blob_sizes selinux_blob_sizes; static inline struct task_security_struct *selinux_cred(const struct cred *cred) {
The SELinux GTP implementation is explained in: Documentation/security/GTP.rst Signed-off-by: Richard Haines <richard_c_haines@btinternet.com> --- Documentation/security/GTP.rst | 61 ++++++++++++++++++++++++++ security/selinux/hooks.c | 66 +++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 + security/selinux/include/objsec.h | 4 ++ 4 files changed, 133 insertions(+)