From laforge at gnumonks.org Mon Oct 12 09:38:51 2020 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 12 Oct 2020 11:38:51 +0200 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: References: <20200930094934.32144-1-richard_c_haines@btinternet.com> <20200930094934.32144-4-richard_c_haines@btinternet.com> <20200930110153.GT3871@nataraja> <33cf57c9599842247c45c92aa22468ec89f7ba64.camel@btinternet.com> <20200930133847.GD238904@nataraja> Message-ID: <20201012093851.GF947663@nataraja> 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 -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From paul at paul-moore.com Mon Oct 12 02:09:11 2020 From: paul at paul-moore.com (Paul Moore) Date: Sun, 11 Oct 2020 22:09:11 -0400 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: <20200930133847.GD238904@nataraja> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> <20200930094934.32144-4-richard_c_haines@btinternet.com> <20200930110153.GT3871@nataraja> <33cf57c9599842247c45c92aa22468ec89f7ba64.camel@btinternet.com> <20200930133847.GD238904@nataraja> Message-ID: On Wed, Sep 30, 2020 at 9:39 AM Harald Welte 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? -- paul moore www.paul-moore.com From paul at paul-moore.com Tue Oct 13 13:55:40 2020 From: paul at paul-moore.com (Paul Moore) Date: Tue, 13 Oct 2020 09:55:40 -0400 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: <20201012093851.GF947663@nataraja> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> <20200930094934.32144-4-richard_c_haines@btinternet.com> <20200930110153.GT3871@nataraja> <33cf57c9599842247c45c92aa22468ec89f7ba64.camel@btinternet.com> <20200930133847.GD238904@nataraja> <20201012093851.GF947663@nataraja> Message-ID: On Mon, Oct 12, 2020 at 5:40 AM Harald Welte 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 -- paul moore www.paul-moore.com From richard_c_haines at btinternet.com Tue Oct 13 16:38:16 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Tue, 13 Oct 2020 17:38:16 +0100 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: References: <20200930094934.32144-1-richard_c_haines@btinternet.com> <20200930094934.32144-4-richard_c_haines@btinternet.com> <20200930110153.GT3871@nataraja> <33cf57c9599842247c45c92aa22468ec89f7ba64.camel@btinternet.com> <20200930133847.GD238904@nataraja> <20201012093851.GF947663@nataraja> Message-ID: <77226ae9dc60113d1953c1f957849d6460c5096f.camel@btinternet.com> On Tue, 2020-10-13 at 09:55 -0400, Paul Moore wrote: > On Mon, Oct 12, 2020 at 5:40 AM Harald Welte > 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 From laforge at gnumonks.org Tue Oct 13 20:42:27 2020 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 13 Oct 2020 22:42:27 +0200 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: <77226ae9dc60113d1953c1f957849d6460c5096f.camel@btinternet.com> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> <20200930094934.32144-4-richard_c_haines@btinternet.com> <20200930110153.GT3871@nataraja> <33cf57c9599842247c45c92aa22468ec89f7ba64.camel@btinternet.com> <20200930133847.GD238904@nataraja> <20201012093851.GF947663@nataraja> <77226ae9dc60113d1953c1f957849d6460c5096f.camel@btinternet.com> Message-ID: <20201013204227.GP947663@nataraja> 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 -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From richard_c_haines at btinternet.com Thu Oct 15 22:51:31 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Thu, 15 Oct 2020 22:51:31 -0000 Subject: [RFC PATCH 1/1] selinux-testsuite: Add GTP tests In-Reply-To: <20200924085314.6120-1-richard_c_haines@btinternet.com> References: <20200924085314.6120-1-richard_c_haines@btinternet.com> Message-ID: <20200924085314.6120-2-richard_c_haines@btinternet.com> Add tests to support the GTP driver. Read the selinux-testsuite/tests/gtp/GTP-README for setup details. Notes: 1) The kernel does not pass back errors on delete link. Need to check audit log for deny gtp { del }. 2) The kernel or the libgtpnl library does not pass back errors on gtp { get }. Seems to be bug or as designed !!. Check audit log for deny. Signed-off-by: Richard Haines --- defconfig | 4 + policy/Makefile | 5 + policy/test_gtp.cil | 18 + policy/test_gtp.te | 96 +++++ tests/Makefile | 4 + tests/gtp/.gitignore | 2 + tests/gtp/GTP-README | 123 ++++++ tests/gtp/Makefile | 8 + ...tpnl-for-SELinux-testsuite-GTP-tests.patch | 366 ++++++++++++++++++ tests/gtp/gtp-link.c | 134 +++++++ tests/gtp/gtp-tunnel.c | 263 +++++++++++++ tests/gtp/test | 169 ++++++++ 12 files changed, 1192 insertions(+) create mode 100644 policy/test_gtp.cil create mode 100644 policy/test_gtp.te create mode 100644 tests/gtp/.gitignore create mode 100644 tests/gtp/GTP-README create mode 100644 tests/gtp/Makefile create mode 100644 tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch create mode 100644 tests/gtp/gtp-link.c create mode 100644 tests/gtp/gtp-tunnel.c create mode 100755 tests/gtp/test diff --git a/defconfig b/defconfig index 46eb673..7b82f19 100644 --- a/defconfig +++ b/defconfig @@ -117,3 +117,7 @@ CONFIG_VFAT_FS=m # They are not required for SELinux operation itself. CONFIG_WATCH_QUEUE=y CONFIG_KEY_NOTIFICATIONS=y + +# GTP module. +# This is not required for SELinux operation itself. +CONFIG_GTP=y diff --git a/policy/Makefile b/policy/Makefile index 6c49091..01aa63f 100644 --- a/policy/Makefile +++ b/policy/Makefile @@ -144,6 +144,11 @@ endif endif endif +ifeq ($(shell test -e /usr/local/include/libgtpnl/gtpnl.h && echo true),true) +TARGETS += test_gtp.te +CIL_TARGETS += test_gtp.cil +endif + ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6)) TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te test_ibpkey.te, $(TARGETS)) endif diff --git a/policy/test_gtp.cil b/policy/test_gtp.cil new file mode 100644 index 0000000..057bcf2 --- /dev/null +++ b/policy/test_gtp.cil @@ -0,0 +1,18 @@ +(class gtp (add del get)) +(classorder (unordered gtp)) + +(allow test_gtp-1_t self (gtp(add del get))) +(allow test_gtp-2_t self (gtp(add del get))) +(allow test_gtp-3_t self (gtp(add del get))) + +(allow test_gtp_no_add_pdp_t test_gtp-1_t (gtp(del get))) +(allow test_gtp_no_del_pdp_t test_gtp-1_t (gtp(add get))) +(allow test_gtp_no_get_pdp_dump_t test_gtp-1_t (gtp(add del))) +(allow test_gtp_no_get_pdp_match_t test_gtp-1_t (gtp(add del))) + +;; Deny gtp for del_link +(allow test_gtp_no_del_link_t self (gtp (add))) +(allow test_gtp-1_t test_gtp_no_del_link_t (gtp (del))) + +;; Allow link to be deleted +(allow test_gtp_no_add_link_t self (gtp (del))) diff --git a/policy/test_gtp.te b/policy/test_gtp.te new file mode 100644 index 0000000..611d972 --- /dev/null +++ b/policy/test_gtp.te @@ -0,0 +1,96 @@ +# +########### Test GTP device driver support ############## +# +attribute gtpdomain; + +# For CONFIG_GTP=m +kernel_request_load_module(gtpdomain) + +################## Create gtp-1 domain ###################### +type test_gtp-1_t; +domain_type(test_gtp-1_t) +unconfined_runs_test(test_gtp-1_t) +typeattribute test_gtp-1_t testdomain; +typeattribute test_gtp-1_t gtpdomain; + +################## Create gtp-2 domain ###################### +type test_gtp-2_t; +domain_type(test_gtp-2_t) +unconfined_runs_test(test_gtp-2_t) +typeattribute test_gtp-2_t testdomain; +typeattribute test_gtp-2_t gtpdomain; + +################## Create gtp-3 domain ###################### +type test_gtp-3_t; +domain_type(test_gtp-3_t) +unconfined_runs_test(test_gtp-3_t) +typeattribute test_gtp-3_t testdomain; +typeattribute test_gtp-3_t gtpdomain; + +# Common gtp rules: +allow gtpdomain self:capability { net_admin }; +allow gtpdomain self:netlink_generic_socket *; +allow gtpdomain self:netlink_route_socket *; +allow gtpdomain self:udp_socket *; +allow gtpdomain test_file_t:dir read; +allow gtpdomain user_home_t:file { execute getattr open read }; +corecmd_check_exec_shell(gtpdomain) +corecmd_exec_bin(gtpdomain) +corecmd_mmap_bin_files(gtpdomain) +corecmd_shell_entry_type(gtpdomain) +corenet_udp_bind_generic_node(gtpdomain) +corenet_udp_bind_generic_port(gtpdomain) +kernel_read_network_state(gtpdomain) +miscfiles_exec_test_files(gtpdomain) +userdom_list_user_home_dirs(gtpdomain) +userdom_manage_user_home_content_dirs(gtpdomain) +userdom_map_user_home_files(gtpdomain) +userdom_read_user_home_content_symlinks(gtpdomain) + +####################### Deny gtp { add_link } ########################## +type test_gtp_no_add_link_t; +domain_type(test_gtp_no_add_link_t) +unconfined_runs_test(test_gtp_no_add_link_t) +typeattribute test_gtp_no_add_link_t testdomain; +typeattribute test_gtp_no_add_link_t gtpdomain; + +####################### Deny gtp { del_link } ########################## +type test_gtp_no_del_link_t; +domain_type(test_gtp_no_del_link_t) +unconfined_runs_test(test_gtp_no_del_link_t) +typeattribute test_gtp_no_del_link_t testdomain; +typeattribute test_gtp_no_del_link_t gtpdomain; + +################## Deny gtp { add_pdp } ######################## +type test_gtp_no_add_pdp_t; +domain_type(test_gtp_no_add_pdp_t) +unconfined_runs_test(test_gtp_no_add_pdp_t) +typeattribute test_gtp_no_add_pdp_t testdomain; +typeattribute test_gtp_no_add_pdp_t gtpdomain; + +################## Deny gtp { del_pdp } ######################## +type test_gtp_no_del_pdp_t; +domain_type(test_gtp_no_del_pdp_t) +unconfined_runs_test(test_gtp_no_del_pdp_t) +typeattribute test_gtp_no_del_pdp_t testdomain; +typeattribute test_gtp_no_del_pdp_t gtpdomain; + +################## Deny gtp { get_pdp } ######################## +type test_gtp_no_get_pdp_dump_t; +domain_type(test_gtp_no_get_pdp_dump_t) +unconfined_runs_test(test_gtp_no_get_pdp_dump_t) +typeattribute test_gtp_no_get_pdp_dump_t testdomain; +typeattribute test_gtp_no_get_pdp_dump_t gtpdomain; + +################## Deny gtp { get_pdp } ######################## +type test_gtp_no_get_pdp_match_t; +domain_type(test_gtp_no_get_pdp_match_t) +unconfined_runs_test(test_gtp_no_get_pdp_match_t) +typeattribute test_gtp_no_get_pdp_match_t testdomain; +typeattribute test_gtp_no_get_pdp_match_t gtpdomain; + +# +########### Allow these domains to be entered from sysadm domain ############ +# +miscfiles_domain_entry_test_files(gtpdomain) +userdom_sysadm_entry_spec_domtrans_to(gtpdomain) diff --git a/tests/Makefile b/tests/Makefile index 001639b..968f68a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -129,6 +129,10 @@ SUBDIRS += watchkey endif endif +ifeq ($(shell test -e /usr/local/include/libgtpnl/gtpnl.h && echo true),true) +SUBDIRS += gtp +endif + ifeq ($(DISTRO),RHEL4) SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS)) endif diff --git a/tests/gtp/.gitignore b/tests/gtp/.gitignore new file mode 100644 index 0000000..decdf8a --- /dev/null +++ b/tests/gtp/.gitignore @@ -0,0 +1,2 @@ +gtp-link +gtp-tunnel diff --git a/tests/gtp/GTP-README b/tests/gtp/GTP-README new file mode 100644 index 0000000..35a4ace --- /dev/null +++ b/tests/gtp/GTP-README @@ -0,0 +1,123 @@ +Testing LSM/SELinux GTP Kernel Hooks +==================================== + +These tests were performed on Fedora 32 Workstation with the 'targeted' policy +using an updated kernel with the GTP RFC kernel patches. + +The basic process is: +1) Build kernel with RFC LSM/GTP/SELinux patches (use the + selinux-testsuite/defconfig file to set correct config if required). +2) Setup the selinux-testsuite and add the GTP test patch. +3) Build/install the libgtpnl library using a patch from the selinux-testsuite + as this will allow errors to be returned by the library functions. +4) Build/run selinux-testsuite for all SELinux tests (sets up the environment). +5) Run the GTP tests locally to see more info. +6) Remove the selinux-testsuite policy. + +# +#### Start ##### +# + +Build and install a kernel with the "Add LSM/SELinux support for GPRS +Tunneling Protocol (GTP)" patch set, [1] was used for these tests. + +NOTE: The selinux-testsuite/defconfig file contains kernel config info to +build a suitable kernel. See selinux-testsuite/README.md + +Make a test build directory e.g.: +mkdir /home/GTP-TEST + +# +#### Setup SELinux-testsuite ###### +# +cd /home/GTP-TEST +git clone https://github.com/SELinuxProject/selinux-testsuite.git +cd selinux-testsuite + +Install the testsuite RFC GTP Patch: "selinux-testsuite: Add GTP tests" + +This will add the GTP tests. There will be in selinux-testsuite/tests/gtp: +1) GTP-README - These install/build/run instructions. +2) Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch - This contains + changes required to return ERRNO and add gtp_match_tunnel function to + the libgtpnl library and tools. +3) gtp-link.c and gtp-tunnel.c - These are the modified files from + libgtpnl/tools as the local Makefile will build these. +4) test - A perl test script. + +# +##### Setup and build/install the libgtpnl library ###### +# +Note: The install process will install the library and include files by +default in /usr/local/..): +cd /home/GTP-TEST +git clone git://git.osmocom.org/libgtpnl.git +cd libgtpnl +patch -p1 < ../selinux-testsuite/tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch +autoreconf -fi && ./configure && make && make install + +Now build and run the SELinux-testsuite: +cd /home/GTP-TEST/selinux-testsuite +setenforce 1 +make test + +If there is a build error it is most likely to be the 'module_load' test that +requires the kernel version devel to be installed. If it is not then comment +out the test in tests/Makefile. + +All other tests should run correctly. The GTP test will be last and there +should be one error reported: + +# Failed test 'FIXME: Fails gtp_list_tunnel() as no callback error. +Audit log should have: allow test_gtp_no_get_pdp_dump_t test_gtp_t:gtp get;' +# at gtp/test line 76. + +This happens because the kernel/netlink does not return an error when +'gtp-tunnel list' is called and the permission is denied, however the audit.log +indicates the denial. Any idea for a fix ??. Tried various kernel/netlink +changes to no avail. Netlink documentation seems to imply that it should work. + +To run the GTP tests locally and see more information: + +cd tests/gtp +# Clear audit log file: +> /var/log/audit/audit.log +# Run tests showing extra info: +./test +# Check audit log for denials: +audit2allow -p /etc/selinux/targeted/policy/policy.32 < /var/log/audit/audit.log + +The output should consist of the following entries: +#============= test_gtp-2_t ============== +allow test_gtp-2_t test_gtp-1_t:gtp { del get }; + +#============= test_gtp_no_add_link_t ============== +allow test_gtp_no_add_link_t self:gtp add; + +#============= test_gtp_no_add_pdp_t ============== +allow test_gtp_no_add_pdp_t test_gtp-1_t:gtp add; + +#============= test_gtp_no_del_link_t ============== +allow test_gtp_no_del_link_t self:gtp del; + +#============= test_gtp_no_del_pdp_t ============== +allow test_gtp_no_del_pdp_t test_gtp-1_t:gtp del; + +#============= test_gtp_no_get_pdp_dump_t ============== +allow test_gtp_no_get_pdp_dump_t test_gtp-1_t:gtp get; + +#============= test_gtp_no_get_pdp_match_t ============== +allow test_gtp_no_get_pdp_match_t test_gtp-1_t:gtp get; + + +IMPORTANT: Remove the selinux-testsuite test policy when finished as it will +stop any libgtpnl functions from working in other SELinux domains: + +cd /home/GTP-TEST/selinux-testsuite +make -C policy unload + +libgtpnl functions should now work in any domain. + +The End + +[1] https://github.com/SELinuxProject/selinux-kernel diff --git a/tests/gtp/Makefile b/tests/gtp/Makefile new file mode 100644 index 0000000..5adc426 --- /dev/null +++ b/tests/gtp/Makefile @@ -0,0 +1,8 @@ +TARGETS = gtp-link gtp-tunnel +CFLAGS ?= -Wall +LDLIBS += -l mnl -lgtpnl + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) diff --git a/tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch b/tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch new file mode 100644 index 0000000..3baef1c --- /dev/null +++ b/tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch @@ -0,0 +1,366 @@ +libgtpnl: Allow SELinux-testsuite to run tests on GTP + +This allows the GTP functions to return errno when running +test so that EACCES can be detected. + +Added 'gtp-tunnel match ' for testing +permissions. + +Added to gtp-link options to pass port numbers when adding device in +the same namespace. + +NOTE: gtp_list_tunnel() does not return an error when pdp_get denied. +Could not find reason for this. gtp_match_tunnel() does return error +when pdp_get denied. + +--- + include/libgtpnl/gtpnl.h | 1 + + src/gtp-genl.c | 47 +++++++++++++++++++++++++---- + src/libgtpnl.map | 1 + + tools/gtp-link.c | 37 ++++++++++++++++++----- + tools/gtp-tunnel.c | 64 +++++++++++++++++++++++++++++++++++----- + 5 files changed, 130 insertions(+), 20 deletions(-) + +diff --git a/include/libgtpnl/gtpnl.h b/include/libgtpnl/gtpnl.h +index 6cd9f46..1bc427d 100644 +--- a/include/libgtpnl/gtpnl.h ++++ b/include/libgtpnl/gtpnl.h +@@ -27,5 +27,6 @@ struct gtp_tunnel; + int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t); + int gtp_del_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t); + int gtp_list_tunnel(int genl_id, struct mnl_socket *nl); ++int gtp_match_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t); + + #endif +diff --git a/src/gtp-genl.c b/src/gtp-genl.c +index f12f872..fe24625 100644 +--- a/src/gtp-genl.c ++++ b/src/gtp-genl.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -66,6 +67,7 @@ int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) + struct nlmsghdr *nlh; + char buf[MNL_SOCKET_BUFFER_SIZE]; + uint32_t seq = time(NULL); ++ int ret; + + if (t->gtp_version > GTP_V1) { + fprintf(stderr, "wrong GTP version %u, use v0 or v1\n", +@@ -77,8 +79,12 @@ int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) + GTP_CMD_NEWPDP); + gtp_build_payload(nlh, t); + +- if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) ++ ret = genl_socket_talk(nl, nlh, seq, NULL, NULL); ++ if (ret < 0) { ++ ret = errno; + perror("genl_socket_talk"); ++ return ret; ++ } + + return 0; + } +@@ -89,13 +95,19 @@ int gtp_del_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t seq = time(NULL); ++ int ret; + + nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_ACK, ++seq, + GTP_CMD_DELPDP); + gtp_build_payload(nlh, t); + +- if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) ++ ret = genl_socket_talk(nl, nlh, seq, NULL, NULL); ++ /* Kernel void gtp_dellink() does not pass errors back to userspace */ ++ if (ret < 0) { ++ ret = errno; + perror("genl_socket_talk"); ++ return ret; ++ } + + return 0; + } +@@ -194,15 +206,40 @@ int gtp_list_tunnel(int genl_id, struct mnl_socket *nl) + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t seq = time(NULL); ++ int ret; + +- nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_DUMP, 0, ++ nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_DUMP | NLM_F_ACK, ++seq, + GTP_CMD_GETPDP); + +- if (genl_socket_talk(nl, nlh, seq, genl_gtp_attr_cb, NULL) < 0) { ++ ret = genl_socket_talk(nl, nlh, seq, genl_gtp_attr_cb, NULL); ++ if (ret < 0) { ++ ret = errno; + perror("genl_socket_talk"); +- return 0; ++ return ret; + } + + return 0; + } + EXPORT_SYMBOL(gtp_list_tunnel); ++ ++int gtp_match_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) ++{ ++ char buf[MNL_SOCKET_BUFFER_SIZE]; ++ struct nlmsghdr *nlh; ++ uint32_t seq = time(NULL); ++ int ret; ++ ++ nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_MATCH | NLM_F_ACK, ++seq, ++ GTP_CMD_GETPDP); ++ gtp_build_payload(nlh, t); ++ ++ ret = genl_socket_talk(nl, nlh, seq, genl_gtp_attr_cb, NULL); ++ if (ret < 0) { ++ ret = errno; ++ perror("genl_socket_talk"); ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(gtp_match_tunnel); +diff --git a/src/libgtpnl.map b/src/libgtpnl.map +index 804f8b3..4556758 100644 +--- a/src/libgtpnl.map ++++ b/src/libgtpnl.map +@@ -14,6 +14,7 @@ global: + gtp_add_tunnel; + gtp_del_tunnel; + gtp_list_tunnel; ++ gtp_match_tunnel; + + gtp_tunnel_alloc; + gtp_tunnel_free; +diff --git a/tools/gtp-link.c b/tools/gtp-link.c +index 8367c6e..e88e349 100644 +--- a/tools/gtp-link.c ++++ b/tools/gtp-link.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -44,35 +45,53 @@ int main(int argc, char *argv[]) + { + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret, sgsn_mode = 0; ++ int port1, port2; + + if (argc < 3) { +- printf("Usage: %s \n", argv[0]); ++ printf("Usage: %s [--sgsn] [port1] [port2]\n", ++ argv[0]); + exit(EXIT_FAILURE); + } + + if (!strcmp(argv[1], "del")) { + printf("destroying gtp interface...\n"); +- if (gtp_dev_destroy(argv[2]) < 0) ++ ++ ret = gtp_dev_destroy(argv[2]); ++ /* Kernel gtp_dellink() does not pass errors back to userspace */ ++ if (ret < 0) { ++ ret = errno; + perror("gtp_dev_destroy"); ++ } + +- return 0; ++ return ret; + } + +- if (argc > 3 && !strcmp(argv[3], "--sgsn")) ++ port1 = 3386; ++ port2 = 2152; ++ ++ if (argc > 3 && !strcmp(argv[3], "--sgsn")) { + sgsn_mode = 1; ++ if (argc == 6) { ++ port1 = atoi(argv[4]); ++ port2 = atoi(argv[5]); ++ } ++ } else if (argc == 5) { ++ port1 = atoi(argv[3]); ++ port2 = atoi(argv[4]); ++ } + + int fd1 = socket(AF_INET, SOCK_DGRAM, 0); + int fd2 = socket(AF_INET, SOCK_DGRAM, 0); + struct sockaddr_in sockaddr_fd1 = { + .sin_family = AF_INET, +- .sin_port = htons(3386), ++ .sin_port = htons(port1), + .sin_addr = { + .s_addr = INADDR_ANY, + }, + }; + struct sockaddr_in sockaddr_fd2 = { + .sin_family = AF_INET, +- .sin_port = htons(2152), ++ .sin_port = htons(port2), + .sin_addr = { + .s_addr = INADDR_ANY, + }, +@@ -94,13 +113,15 @@ int main(int argc, char *argv[]) + else + ret = gtp_dev_create(-1, argv[2], fd1, fd2); + if (ret < 0) { +- perror("cannot create GTP device\n"); +- exit(EXIT_FAILURE); ++ ret = errno; ++ perror("cannot create GTP device"); ++ return ret; + } + + fprintf(stderr, "WARNING: attaching dummy socket descriptors. Keep " + "this process running for testing purposes.\n"); + ++ + while (1) { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); +diff --git a/tools/gtp-tunnel.c b/tools/gtp-tunnel.c +index 513ff4a..8fb7fa2 100644 +--- a/tools/gtp-tunnel.c ++++ b/tools/gtp-tunnel.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++ + #include + #include + #include +@@ -56,7 +57,7 @@ add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) + uint32_t gtp_ifidx; + struct in_addr ms, sgsn; + uint32_t gtp_version; +- int optidx; ++ int optidx, ret; + + if (argc < 7 || argc > 8) { + add_usage(argv[0]); +@@ -107,10 +108,11 @@ add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) + } + gtp_tunnel_set_sgsn_ip4(t, &sgsn); + +- gtp_add_tunnel(genl_id, nl, t); ++ /* Returns 0 or errno */ ++ ret = gtp_add_tunnel(genl_id, nl, t); + + gtp_tunnel_free(t); +- return 0; ++ return ret; + } + + static int +@@ -118,6 +120,7 @@ del_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) + { + struct gtp_tunnel *t; + uint32_t gtp_ifidx; ++ int ret; + + if (argc != 5) { + printf("%s add \n", +@@ -146,10 +149,11 @@ del_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) + return EXIT_FAILURE; + } + +- gtp_del_tunnel(genl_id, nl, t); ++ /* Returns 0 or errno */ ++ ret = gtp_del_tunnel(genl_id, nl, t); + + gtp_tunnel_free(t); +- return 0; ++ return ret; + } + + struct gtp_pdp { +@@ -170,7 +174,51 @@ struct gtp_pdp { + static int + list_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) + { +- return gtp_list_tunnel(genl_id, nl); ++ int ret; ++ ++ ret = gtp_list_tunnel(genl_id, nl); ++ return ret; ++} ++ ++static int ++match_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) ++{ ++ struct gtp_tunnel *t; ++ uint32_t gtp_ifidx; ++ int ret; ++ ++ if (argc != 5) { ++ printf("%s match \n", ++ argv[0]); ++ return EXIT_FAILURE; ++ } ++ ++ t = gtp_tunnel_alloc(); ++ ++ gtp_ifidx = if_nametoindex(argv[2]); ++ if (gtp_ifidx == 0) { ++ fprintf(stderr, "wrong GTP interface %s\n", argv[2]); ++ return EXIT_FAILURE; ++ } ++ gtp_tunnel_set_ifidx(t, gtp_ifidx); ++ ++ if (strcmp(argv[3], "v0") == 0) { ++ gtp_tunnel_set_version(t, GTP_V0); ++ gtp_tunnel_set_tid(t, atoi(argv[4])); ++ } else if (strcmp(argv[3], "v1") == 0) { ++ gtp_tunnel_set_version(t, GTP_V1); ++ gtp_tunnel_set_i_tei(t, atoi(argv[4])); ++ } else { ++ fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", ++ argv[3]); ++ return EXIT_FAILURE; ++ } ++ ++ /* Returns 0 or errno */ ++ ret = gtp_match_tunnel(genl_id, nl, t); ++ ++ gtp_tunnel_free(t); ++ return ret; + } + + int main(int argc, char *argv[]) +@@ -180,7 +228,7 @@ int main(int argc, char *argv[]) + int ret; + + if (argc < 2) { +- printf("%s []\n", argv[0]); ++ printf("%s []\n", argv[0]); + exit(EXIT_FAILURE); + } + +@@ -202,6 +250,8 @@ int main(int argc, char *argv[]) + ret = del_tunnel(argc, argv, genl_id, nl); + else if (strncmp(argv[1], "list", strlen(argv[1])) == 0) + ret = list_tunnel(argc, argv, genl_id, nl); ++ else if (strncmp(argv[1], "match", strlen(argv[1])) == 0) ++ ret = match_tunnel(argc, argv, genl_id, nl); + else { + printf("Unknown command `%s'\n", argv[1]); + exit(EXIT_FAILURE); +-- +2.26.2 + diff --git a/tests/gtp/gtp-link.c b/tests/gtp/gtp-link.c new file mode 100644 index 0000000..c94a75b --- /dev/null +++ b/tests/gtp/gtp-link.c @@ -0,0 +1,134 @@ +/* Command line utility to create GTP link */ + +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * (C) 2016 by Pablo Neira Ayuso + * + * Author: Pablo Neira Ayuso + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret, sgsn_mode = 0; + int port1, port2; + + if (argc < 3) { + printf("Usage: %s [--sgsn] [port1] [port2]\n", + argv[0]); + exit(EXIT_FAILURE); + } + + if (!strcmp(argv[1], "del")) { + printf("destroying gtp interface...\n"); + + ret = gtp_dev_destroy(argv[2]); + /* Kernel gtp_dellink() does not pass errors back to userspace */ + if (ret < 0) { + ret = errno; + perror("gtp_dev_destroy"); + } + + return ret; + } + + port1 = 3386; + port2 = 2152; + + if (argc > 3 && !strcmp(argv[3], "--sgsn")) { + sgsn_mode = 1; + if (argc == 6) { + port1 = atoi(argv[4]); + port2 = atoi(argv[5]); + } + } else if (argc == 5) { + port1 = atoi(argv[3]); + port2 = atoi(argv[4]); + } + + int fd1 = socket(AF_INET, SOCK_DGRAM, 0); + int fd2 = socket(AF_INET, SOCK_DGRAM, 0); + struct sockaddr_in sockaddr_fd1 = { + .sin_family = AF_INET, + .sin_port = htons(port1), + .sin_addr = { + .s_addr = INADDR_ANY, + }, + }; + struct sockaddr_in sockaddr_fd2 = { + .sin_family = AF_INET, + .sin_port = htons(port2), + .sin_addr = { + .s_addr = INADDR_ANY, + }, + }; + + if (bind(fd1, (struct sockaddr *) &sockaddr_fd1, + sizeof(sockaddr_fd1)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + if (bind(fd2, (struct sockaddr *) &sockaddr_fd2, + sizeof(sockaddr_fd2)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + + if (sgsn_mode) + ret = gtp_dev_create_sgsn(-1, argv[2], fd1, fd2); + else + ret = gtp_dev_create(-1, argv[2], fd1, fd2); + if (ret < 0) { + ret = errno; + perror("cannot create GTP device"); + return ret; + } + + fprintf(stderr, "WARNING: attaching dummy socket descriptors. Keep " + "this process running for testing purposes.\n"); + + while (1) { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + ret = recvfrom(fd1, buf, sizeof(buf), 0, + (struct sockaddr *)&addr, &len); + printf("received %d bytes via UDP socket\n", ret); + } + + return 0; +} diff --git a/tests/gtp/gtp-tunnel.c b/tests/gtp/gtp-tunnel.c new file mode 100644 index 0000000..6079028 --- /dev/null +++ b/tests/gtp/gtp-tunnel.c @@ -0,0 +1,263 @@ +/* Command line utility to create GTP tunnels (PDP contexts) */ + +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * (C) 2016 by Pablo Neira Ayuso + * + * Author: Pablo Neira Ayuso + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +static void add_usage(const char *name) +{ + printf("%s add \n", + name); + printf("%s add \n", + name); +} + +static int +add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) +{ + struct gtp_tunnel *t; + uint32_t gtp_ifidx; + struct in_addr ms, sgsn; + uint32_t gtp_version; + int optidx, ret; + + if (argc < 7 || argc > 8) { + add_usage(argv[0]); + return EXIT_FAILURE; + } + + t = gtp_tunnel_alloc(); + optidx = 2; + + gtp_ifidx = if_nametoindex(argv[optidx]); + if (gtp_ifidx == 0) { + fprintf(stderr, "wrong GTP interface %s\n", argv[optidx]); + return EXIT_FAILURE; + } + gtp_tunnel_set_ifidx(t, gtp_ifidx); + + optidx++; + + if (strcmp(argv[optidx], "v0") == 0) + gtp_version = GTP_V0; + else if (strcmp(argv[optidx], "v1") == 0) + gtp_version = GTP_V1; + else { + fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", + argv[optidx]); + return EXIT_FAILURE; + } + gtp_tunnel_set_version(t, gtp_version); + + optidx++; + + if (gtp_version == GTP_V0) + gtp_tunnel_set_tid(t, atoi(argv[optidx++])); + else if (gtp_version == GTP_V1) { + gtp_tunnel_set_i_tei(t, atoi(argv[optidx++])); + gtp_tunnel_set_o_tei(t, atoi(argv[optidx++])); + } + + if (inet_aton(argv[optidx++], &ms) < 0) { + perror("bad address for ms"); + exit(EXIT_FAILURE); + } + gtp_tunnel_set_ms_ip4(t, &ms); + + if (inet_aton(argv[optidx++], &sgsn) < 0) { + perror("bad address for sgsn"); + exit(EXIT_FAILURE); + } + gtp_tunnel_set_sgsn_ip4(t, &sgsn); + + /* Returns 0 or errno */ + ret = gtp_add_tunnel(genl_id, nl, t); + + gtp_tunnel_free(t); + return ret; +} + +static int +del_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) +{ + struct gtp_tunnel *t; + uint32_t gtp_ifidx; + int ret; + + if (argc != 5) { + printf("%s add \n", + argv[0]); + return EXIT_FAILURE; + } + + t = gtp_tunnel_alloc(); + + gtp_ifidx = if_nametoindex(argv[2]); + if (gtp_ifidx == 0) { + fprintf(stderr, "wrong GTP interface %s\n", argv[2]); + return EXIT_FAILURE; + } + gtp_tunnel_set_ifidx(t, gtp_ifidx); + + if (strcmp(argv[3], "v0") == 0) { + gtp_tunnel_set_version(t, GTP_V0); + gtp_tunnel_set_tid(t, atoi(argv[4])); + } else if (strcmp(argv[3], "v1") == 0) { + gtp_tunnel_set_version(t, GTP_V1); + gtp_tunnel_set_i_tei(t, atoi(argv[4])); + } else { + fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", + argv[3]); + return EXIT_FAILURE; + } + + /* Returns 0 or errno */ + ret = gtp_del_tunnel(genl_id, nl, t); + + gtp_tunnel_free(t); + return ret; +} + +struct gtp_pdp { + uint32_t version; + union { + struct { + uint64_t tid; + } v0; + struct { + uint32_t i_tei; + uint32_t o_tei; + } v1; + } u; + struct in_addr sgsn_addr; + struct in_addr ms_addr; +}; + +static int +list_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) +{ + int ret; + + ret = gtp_list_tunnel(genl_id, nl); + return ret; +} + +static int +match_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) +{ + struct gtp_tunnel *t; + uint32_t gtp_ifidx; + int ret; + + if (argc != 5) { + printf("%s match \n", + argv[0]); + return EXIT_FAILURE; + } + + t = gtp_tunnel_alloc(); + + gtp_ifidx = if_nametoindex(argv[2]); + if (gtp_ifidx == 0) { + fprintf(stderr, "wrong GTP interface %s\n", argv[2]); + return EXIT_FAILURE; + } + gtp_tunnel_set_ifidx(t, gtp_ifidx); + + if (strcmp(argv[3], "v0") == 0) { + gtp_tunnel_set_version(t, GTP_V0); + gtp_tunnel_set_tid(t, atoi(argv[4])); + } else if (strcmp(argv[3], "v1") == 0) { + gtp_tunnel_set_version(t, GTP_V1); + gtp_tunnel_set_i_tei(t, atoi(argv[4])); + } else { + fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", + argv[3]); + return EXIT_FAILURE; + } + + /* Returns 0 or errno */ + ret = gtp_match_tunnel(genl_id, nl, t); + + gtp_tunnel_free(t); + return ret; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + int32_t genl_id; + int ret; + + if (argc < 2) { + printf("%s []\n", argv[0]); + exit(EXIT_FAILURE); + } + + nl = genl_socket_open(); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + genl_id = genl_lookup_family(nl, "gtp"); + if (genl_id < 0) { + printf("not found gtp genl family\n"); + exit(EXIT_FAILURE); + } + + if (strncmp(argv[1], "add", strlen(argv[1])) == 0) + ret = add_tunnel(argc, argv, genl_id, nl); + else if (strncmp(argv[1], "delete", strlen(argv[1])) == 0) + ret = del_tunnel(argc, argv, genl_id, nl); + else if (strncmp(argv[1], "list", strlen(argv[1])) == 0) + ret = list_tunnel(argc, argv, genl_id, nl); + else if (strncmp(argv[1], "match", strlen(argv[1])) == 0) + ret = match_tunnel(argc, argv, genl_id, nl); + else { + printf("Unknown command `%s'\n", argv[1]); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return ret; +} diff --git a/tests/gtp/test b/tests/gtp/test new file mode 100755 index 0000000..cff8eab --- /dev/null +++ b/tests/gtp/test @@ -0,0 +1,169 @@ +#!/usr/bin/perl +use Test::More; + +BEGIN { + $basedir = $0; + $basedir =~ s|(.*)/[^/]*|$1|; + + plan tests => 20; +} + +sub add_link { + my ( $runcon_args, $args ) = @_; + my $pid; + + if ( ( $pid = fork() ) == 0 ) { + exec "runcon $runcon_args $basedir/gtp-link $args"; + } + + # Wait for it to initialize. + sleep 1; + return $pid; +} + +sub del_link { + my ($pid) = @_; + + kill KILL, $pid; + waitpid $pid, 0; +} + +############ Basic tests for GTP ############# +print "Test GTP device driver support\n"; +$pid = add_link( "-t test_gtp-1_t", "add gtp-1 2>&1" ); + +print "Test GTP device driver support\n"; +$result = system +"runcon -t test_gtp-1_t $basedir/gtp-tunnel add gtp-1 v1 100 200 127.0.0.1 127.0.0.1"; +ok( $result eq 0 ); + +$result = system +"runcon -t test_gtp-1_t $basedir/gtp-tunnel add gtp-1 v1 200 300 127.0.0.2 127.0.0.2"; +ok( $result eq 0 ); + +$result = system +"runcon -t test_gtp-1_t $basedir/gtp-tunnel add gtp-1 v0 300 127.0.0.3 127.0.0.3"; +ok( $result eq 0 ); + +$result = system "runcon -t test_gtp-1_t $basedir/gtp-tunnel list"; +ok( $result eq 0 ); + +$result = + system "runcon -t test_gtp-1_t $basedir/gtp-tunnel match gtp-1 v1 200"; +ok( $result eq 0 ); + +########### Test Deny permissions #################### +print "Test Deny permissions\n"; + +# Deny gtp { add } - EACCES +$result = system +"runcon -t test_gtp_no_add_pdp_t $basedir/gtp-tunnel add gtp-1 v0 400 127.0.0.4 127.0.0.4 2>&1"; +ok( $result >> 8 eq 13 ); + +# Deny gtp { del } - EACCES +$result = system +"runcon -t test_gtp_no_del_pdp_t $basedir/gtp-tunnel delete gtp-1 v1 100 2>&1"; +ok( $result >> 8 eq 13 ); + +# Deny gtp { get } (gtp-tunnel list) - EACCES +# Test returns 0 not EACCES as gtp_list_tunnel() with NLM_F_DUMP does +# not pass errors back via the gtp-genl.c genl_gtp_attr_cb() callback. +# The documentation found suggests that it should !!!! +# The audit log will show the denial: +# allow test_gtp_no_get_pdp_dump_t test_gtp-1_t:gtp get; +$result = + system "runcon -t test_gtp_no_get_pdp_dump_t $basedir/gtp-tunnel list 2>&1"; +ok( + $result >> 8 eq 13, +"FIXME: Fails gtp_list_tunnel() as no callback error. Audit log should have: allow test_gtp_no_get_pdp_dump_t test_gtp-1_t:gtp get;" +); + +print "Deny gtp { get } (gtp-tunnel match) - EACCES\n"; +$result = + system +"runcon -t test_gtp_no_get_pdp_match_t $basedir/gtp-tunnel match gtp-1 v0 300 2>&1"; +ok( $result >> 8 eq 13 ); + +# Kill the link. +$result = system "runcon -t test_gtp-1_t $basedir/gtp-link del gtp-1"; +ok( $result eq 0 ); +del_link($pid); + +# Add link to test deny gtp delete link +$pid = add_link( "-t test_gtp_no_del_link_t", "add gtp-1 2>&1" ); + +# Test returns 0 not EACCES as kernel void gtp_dellink() does not +# pass errors back to userspace. The audit log should show +# allow test_gtp_no_del_link_t self:gtp del; +$result = + system "runcon -t test_gtp_no_del_link_t $basedir/gtp-link del gtp-1 2>&1"; +ok( + $result eq 0, +"PASS: Kernel void gtp_dellink() does not pass errors back. Audit log should have: allow test_gtp_no_del_link_t self:gtp del;" +); + +# Kill the link. +$result = system "runcon -t test_gtp-1_t $basedir/gtp-link del gtp-1"; +del_link($pid); + +# Deny gtp { add } - EACCES +$result = + system "runcon -t test_gtp_no_add_link_t $basedir/gtp-link add gtp-2 2>&1"; +ok( $result >> 8 eq 13 ); + +# +print +"Create three GTP devices with different security contexts in same namespace\n"; +# +$port1 = "3386"; +$port2 = "2152"; + +$pid1 = add_link( "-t test_gtp-1_t", "add gtp-1 $port1 $port2 2>&1" ); + +$result = system +"runcon -t test_gtp-1_t $basedir/gtp-tunnel add gtp-1 v1 200 100 172.99.0.1 172.0.0.1"; +ok( $result eq 0 ); + +$port1++; +$port2++; +$pid2 = add_link( "-t test_gtp-2_t", "add gtp-2 $port1 $port2 2>&1" ); +$result = system +"runcon -t test_gtp-2_t $basedir/gtp-tunnel add gtp-2 v1 200 100 172.99.0.2 172.0.0.2"; +ok( $result eq 0 ); + +$result = system +"runcon -t test_gtp-2_t $basedir/gtp-tunnel list gtp-2 v1 200 100 172.99.0.2 172.0.0.2"; +ok( $result eq 0 ); + +$result = + system "runcon -t test_gtp-2_t $basedir/gtp-tunnel match gtp-1 v1 200 2>&1"; +ok( $result >> 8 eq 13 ); + +$port1++; +$port2++; +$pid3 = add_link( "-t test_gtp-3_t", "add gtp-3 $port1 $port2 2>&1" ); + +# Use test_gtp-2_t to kill link 1. +$result = system "runcon -t test_gtp-2_t $basedir/gtp-link del gtp-1"; +ok( + $result eq 0, +"PASS: Kernel void gtp_dellink() does not pass errors back. Audit log should have: allow test_gtp-2_t test_gtp-1_t:gtp del;" +); +del_link($pid1); + +# Kill link 1. +$result = system "runcon -t test_gtp-1_t $basedir/gtp-link del gtp-1"; +ok( $result eq 0 ); +del_link($pid1); + +# Kill link 2. +$result = system "runcon -t test_gtp-2_t $basedir/gtp-link del gtp-2"; +ok( $result eq 0 ); +del_link($pid2); + +# Kill link 3. +$result = system "runcon -t test_gtp-3_t $basedir/gtp-link del gtp-3"; +ok( $result eq 0 ); +del_link($pid3); + +exit; -- 2.26.2 From richard_c_haines at btinternet.com Fri Oct 16 00:21:04 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Fri, 16 Oct 2020 00:21:04 -0000 Subject: [RFC PATCH 0/1] selinux-testsuite: Add GTP tests Message-ID: <20200924085314.6120-1-richard_c_haines@btinternet.com> These tests were performed on Fedora 32 Workstation with the 'targeted' policy using an updated kernel with the GTP RFC kernel patches. See the tests/gtp/GTP-README for detailed setup/testing. The libgtpnl patch is at: tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch The basic process is: 1) Build kernel with RFC LSM/GTP/SELinux patches (use the selinux-testsuite/defconfig file to set correct config if required). 2) Setup the selinux-testsuite and add the GTP test patch. 3) Build/install the libgtpnl library using a patch from the selinux-testsuite as this will allow errors to be returned by the library functions. 4) Build/run selinux-testsuite for all SELinux tests (sets up the environment). 5) Run the GTP tests locally to see more info. 6) Remove the selinux-testsuite policy. Richard Haines (1): selinux-testsuite: Add GTP tests defconfig | 4 + policy/Makefile | 5 + policy/test_gtp.cil | 18 + policy/test_gtp.te | 96 +++++ tests/Makefile | 4 + tests/gtp/.gitignore | 2 + tests/gtp/GTP-README | 123 ++++++ tests/gtp/Makefile | 8 + ...tpnl-for-SELinux-testsuite-GTP-tests.patch | 366 ++++++++++++++++++ tests/gtp/gtp-link.c | 134 +++++++ tests/gtp/gtp-tunnel.c | 263 +++++++++++++ tests/gtp/test | 169 ++++++++ 12 files changed, 1192 insertions(+) create mode 100644 policy/test_gtp.cil create mode 100644 policy/test_gtp.te create mode 100644 tests/gtp/.gitignore create mode 100644 tests/gtp/GTP-README create mode 100644 tests/gtp/Makefile create mode 100644 tests/gtp/Update-libgtpnl-for-SELinux-testsuite-GTP-tests.patch create mode 100644 tests/gtp/gtp-link.c create mode 100644 tests/gtp/gtp-tunnel.c create mode 100755 tests/gtp/test -- 2.26.2 From lynxis at fe80.eu Fri Oct 16 01:31:55 2020 From: lynxis at fe80.eu (Alexander 'lynxis' Couzens) Date: Fri, 16 Oct 2020 03:31:55 +0200 Subject: [RFC] NS VTY interface Message-ID: <20201016033155.17172a96@lazus.yip> Hi, with the new NS2 code [1] the vty keep compatible. However the new NS2 code is more flexible and support more use cases except the old vty doesn't allow it. I've created an osmocom ticket [2] to experiment and write a draft of the new VTY commands. I would be nice if you can give me some feedback here. Best, lynxis [1] NS <> NS2. it's still the same protocol, just a second implementation of NS. [2] https://osmocom.org/issues/4770 new vty example: 1.1. sgsn with udp bind - ipa style 1.2. sgsn with udp bind - with persistent nsvc 1.3. sgsn with sns listen on all interfaces 1.4. sgsn with sns listen on specific interface 1.5. sgsn with fr 2.1. TODO: pcu with binds to use when receiving info ind 2.2. TODO: pcu with static configuration
;; 1.1. sgsn with udp bind - dynamic with ipa style

ns
 bind udp some
  listen 192.168.0.2 23000
  allow-block-reset-nsvci
;; 1.2. sgsn with udp bind - no dynamic connection - only vty
configured NSE (persistent)

ns
 bind udp some
  listen 192.168.0.2 23000
 nsei 1001
  nsvc udp some 10.0.1.2 23000
;; 1.2. sgsn with udp bind - no dynamic connection - only vty
configured NSE (persistent)

ns
 bind udp some
  listen 192.168.0.2 23000
 bind udp other
  listen 192.168.1.2 23000
 nsei 1001
  ;; will use all bindings
  nsvc udp * 10.0.1.2 23000
 nsei 1002
  nsvc udp other 10.0.1.3 23000
  nsvc udp some 10.0.1.3 23000
;; 1.3. sgsn with sns listen on all interfaces
ns
 bind udp some
  listen 192.168.0.2 23000
  allow-sns group all
 bind udp other
  listen 192.168.1.2 23000
  allow-sns group all
;; 1.4. sgsn with sns listen on specific interface

ns
 bind udp some
  listen 192.168.0.2 23000
  allow-sns group alice
 bind udp other
  listen 192.168.1.2 23000
  allow-sns group bob
;; 1.5. sgsn with fr

fr
 link hdlc1
 link hdlc2

ns
 nsei 1002
  nsvc fr hdlc1 dlci 10
  nsvc fr hdlc2 dlci 10
-- Alexander Couzens mail: lynxis at fe80.eu jabber: lynxis at fe80.eu gpg: 390D CF78 8BF9 AA50 4F8F F1E2 C29E 9DA6 A0DF 8604 -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From richard_c_haines at btinternet.com Thu Oct 15 22:44:04 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Thu, 15 Oct 2020 22:44:04 -0000 Subject: [PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: <20200930094934.32144-1-richard_c_haines@btinternet.com> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> Message-ID: <20200930094934.32144-4-richard_c_haines@btinternet.com> The SELinux GTP implementation is explained in: Documentation/security/GTP.rst Signed-off-by: Richard Haines --- 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(+) 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 #include #include +#include #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) { -- 2.26.2 From richard_c_haines at btinternet.com Thu Oct 15 22:47:48 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Thu, 15 Oct 2020 22:47:48 -0000 Subject: [PATCH 2/3] gtp: Add LSM hooks to GPRS Tunneling Protocol (GTP) In-Reply-To: <20200930094934.32144-1-richard_c_haines@btinternet.com> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> Message-ID: <20200930094934.32144-3-richard_c_haines@btinternet.com> 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 --- 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 From richard_c_haines at btinternet.com Thu Oct 15 22:47:52 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Thu, 15 Oct 2020 22:47:52 -0000 Subject: [PATCH 1/3] security: Add GPRS Tunneling Protocol (GTP) security hooks In-Reply-To: <20200930094934.32144-1-richard_c_haines@btinternet.com> References: <20200930094934.32144-1-richard_c_haines@btinternet.com> Message-ID: <20200930094934.32144-2-richard_c_haines@btinternet.com> The GTP security hooks are explained in: Documentation/security/GTP.rst Signed-off-by: Richard Haines --- Documentation/security/GTP.rst | 39 ++++++++++++++++++++++++++++++++ Documentation/security/index.rst | 1 + include/linux/lsm_hook_defs.h | 3 +++ include/linux/lsm_hooks.h | 13 +++++++++++ include/linux/security.h | 22 ++++++++++++++++++ security/security.c | 18 +++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 Documentation/security/GTP.rst diff --git a/Documentation/security/GTP.rst b/Documentation/security/GTP.rst new file mode 100644 index 000000000..c748587ec --- /dev/null +++ b/Documentation/security/GTP.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================= +GPRS Tunneling Protocol (GTP) +============================= + +GTP LSM Support +=============== + +Security Hooks +-------------- +For security module support, three GTP specific hooks have been implemented:: + + security_gtp_dev_alloc() + security_gtp_dev_free() + security_gtp_dev_cmd() + + +security_gtp_dev_alloc() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to allocate a security structure for a GTP device. Returns a +zero on success, negative values on failure. +If successful the GTP device ``struct gtp_dev`` will hold the allocated +pointer in ``void *security;``. + + +security_gtp_dev_free() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to free the security structure for a GTP device. Returns a +zero on success, negative values on failure. + + +security_gtp_dev_cmd() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to validate a command for the selected GTP device. Returns a +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 };`` diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst index 8129405eb..cdbdaa83b 100644 --- a/Documentation/security/index.rst +++ b/Documentation/security/index.rst @@ -16,3 +16,4 @@ Security Documentation siphash tpm/index digsig + GTP diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 2a8c74d99..ad4bbe042 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -322,6 +322,9 @@ LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname, struct sockaddr *address, int addrlen) LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_endpoint *ep, struct sock *sk, struct sock *newsk) +LSM_HOOK(int, 0, gtp_dev_alloc_security, struct gtp_dev *gtp) +LSM_HOOK(int, 0, gtp_dev_free_security, struct gtp_dev *gtp) +LSM_HOOK(int, 0, gtp_dev_cmd, struct gtp_dev *gtp, enum gtp_genl_cmds cmd) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9e2e3e637..cd73319b9 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -982,6 +982,19 @@ * This hook can be used by the module to update any security state * associated with the TUN device's security structure. * @security pointer to the TUN devices's security structure. + * @gtp_dev_alloc_security: + * Allocate and attach a security structure to the gtp->security field. + * @gtp contains the GTP device structure to secure. + * Returns a zero on success, negative values on failure. + * @gtp_dev_free_security: + * Deallocate and free the security structure stored in gtp->security. + * @gtp contains the GTP device structure to free. + * Returns a zero on success, negative values on failure. + * @gtp_dev_cmd: + * Check permissions according to the @cmd. + * @gtp contains the GTP device to access. + * @cmd contains the GTP command. + * Returns a zero on success, negative values on failure. * * Security hooks for SCTP * diff --git a/include/linux/security.h b/include/linux/security.h index 0a0a03b36..e214605c2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -30,6 +30,7 @@ #include #include #include +#include struct linux_binprm; struct cred; @@ -58,6 +59,8 @@ struct fs_parameter; enum fs_value_type; struct watch; struct watch_notification; +struct gtp_dev; +enum gtp_genl_cmds; /* Default (no) options for the capable function */ #define CAP_OPT_NONE 0x0 @@ -1365,6 +1368,9 @@ int security_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address, int addrlen); void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, struct sock *newsk); +int security_gtp_dev_alloc(struct gtp_dev *gtp); +int security_gtp_dev_free(struct gtp_dev *gtp); +int security_gtp_dev_cmd(struct gtp_dev *gtp, enum gtp_genl_cmds cmd); #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct sock *sock, @@ -1582,6 +1588,22 @@ static inline void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *newsk) { } + +static inline int security_gtp_dev_alloc(struct gtp_dev *gtp) +{ + return 0; +} + +static inline int security_gtp_dev_free(struct gtp_dev *gtp) +{ + return 0; +} + +static inline int security_gtp_dev_cmd(struct gtp_dev *gtp, + enum gtp_genl_cmds cmd) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND diff --git a/security/security.c b/security/security.c index 70a7ad357..12699a789 100644 --- a/security/security.c +++ b/security/security.c @@ -2304,6 +2304,24 @@ void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, } EXPORT_SYMBOL(security_sctp_sk_clone); +int security_gtp_dev_alloc(struct gtp_dev *gtp) +{ + return call_int_hook(gtp_dev_alloc_security, 0, gtp); +} +EXPORT_SYMBOL(security_gtp_dev_alloc); + +int security_gtp_dev_free(struct gtp_dev *gtp) +{ + return call_int_hook(gtp_dev_free_security, 0, gtp); +} +EXPORT_SYMBOL(security_gtp_dev_free); + +int security_gtp_dev_cmd(struct gtp_dev *gtp, enum gtp_genl_cmds cmd) +{ + return call_int_hook(gtp_dev_cmd, 0, gtp, cmd); +} +EXPORT_SYMBOL(security_gtp_dev_cmd); + #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -- 2.26.2 From richard_c_haines at btinternet.com Fri Oct 16 02:49:31 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Fri, 16 Oct 2020 02:49:31 -0000 Subject: [PATCH 0/3] Add LSM/SELinux support for GPRS Tunneling Protocol (GTP) Message-ID: <20200930094934.32144-1-richard_c_haines@btinternet.com> These patches came about after looking at 5G open source in particular the updated 5G GTP driver at [1]. As this driver is still under development, added the LSM/SELinux hooks to the current stable GTP version in kernel selinux-next [2]. Similar hooks have also been implemented in [1] as it uses the same base code as the current 3G version (except that it handles different packet types). To test the 3G GTP driver there is an RFC patch for the selinux-testsuite at [3]. To enable the selinux-testsuite GTP tests, the libgtpnl [4] library and tools needed to be modified to: Return ERRNO on error to detect EACCES, Add gtp_match_tunnel function, Allow gtp-link to specify port numbers for multiple instances to run in the same namespace. A patch for libgtpnl is supplied in the selinux-testsuite patch as well as setup/test instructions (libgtpnl is not packaged by Fedora) These patches were tested on Fedora 32 with kernel [2] using the 'targeted' policy. Also ran the Linux Kernel GTP-U basic tests [5]. [1] https://github.com/PrinzOwO/gtp5g [2] https://github.com/SELinuxProject/selinux-kernel [3] https://lore.kernel.org/selinux/20200924085314.6120-1-richard_c_haines at btinternet.com/ [4] git://git.osmocom.org/libgtpnl.git [5] https://osmocom.org/projects/linux-kernel-gtp-u/wiki/Basic_Testing Changes from RFC patches: 1) Rework the LSM hook names and contents as suggested by Casey Schaufler. This resulted in moving the gtp_dev struct from gtp.c to include/net/gtp.h so that it is visible to the LSM modules for storing the security blob. 2) Remove pr_debug's from gtp.c security_* calls. 3) Minor GTP.rst updates. 4) Added netdev to distribution list. Richard Haines (3): security: Add GPRS Tunneling Protocol (GTP) security hooks gtp: Add LSM hooks to GPRS Tunneling Protocol (GTP) selinux: Add SELinux GTP support Documentation/security/GTP.rst | 100 ++++++++++++++++++++++++++++ Documentation/security/index.rst | 1 + drivers/net/gtp.c | 50 +++++++++----- include/linux/lsm_hook_defs.h | 3 + include/linux/lsm_hooks.h | 13 ++++ include/linux/security.h | 22 ++++++ include/net/gtp.h | 21 ++++++ security/security.c | 18 +++++ security/selinux/hooks.c | 66 ++++++++++++++++++ security/selinux/include/classmap.h | 2 + security/selinux/include/objsec.h | 4 ++ 11 files changed, 284 insertions(+), 16 deletions(-) create mode 100644 Documentation/security/GTP.rst -- 2.26.2 From richard_c_haines at btinternet.com Fri Oct 16 22:43:31 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Fri, 16 Oct 2020 22:43:31 -0000 Subject: [RFC PATCH 1/3] security: Add GPRS Tunneling Protocol (GTP) security hooks In-Reply-To: <20200924085102.5960-1-richard_c_haines@btinternet.com> References: <20200924085102.5960-1-richard_c_haines@btinternet.com> Message-ID: <20200924085102.5960-2-richard_c_haines@btinternet.com> The GTP security hooks are explained in: Documentation/security/GTP.rst Signed-off-by: Richard Haines --- Documentation/security/GTP.rst | 39 ++++++++++++++++++++++++++++++++ Documentation/security/index.rst | 1 + include/linux/lsm_hook_defs.h | 3 +++ include/linux/lsm_hooks.h | 16 +++++++++++++ include/linux/security.h | 19 ++++++++++++++++ security/security.c | 18 +++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 Documentation/security/GTP.rst diff --git a/Documentation/security/GTP.rst b/Documentation/security/GTP.rst new file mode 100644 index 000000000..e307d0b59 --- /dev/null +++ b/Documentation/security/GTP.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================= +GPRS Tunneling Protocol (GTP) +============================= + +GTP LSM Support +=============== + +Security Hooks +-------------- +For security module support, three GTP specific hooks have been implemented:: + + security_gtp_dev_add() + security_gtp_dev_del() + security_gtp_dev_cmd() + + +security_gtp_dev_add() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to allocate a security structure for a GTP device. Returns a +zero on success, negative values on failure. +If successful the GTP device ``struct gtp_dev`` will hold the allocated +pointer in ``void *security;``. + + +security_gtp_dev_del() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to free the security structure for a GTP device. Returns a +zero on success, negative values on failure. + + +security_gtp_dev_cmd() +~~~~~~~~~~~~~~~~~~~~~~ +Allows a module to validate a command for the selected GTP device. Returns a +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 };`` diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst index 8129405eb..cdbdaa83b 100644 --- a/Documentation/security/index.rst +++ b/Documentation/security/index.rst @@ -16,3 +16,4 @@ Security Documentation siphash tpm/index digsig + GTP diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 2a8c74d99..a994417fb 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -322,6 +322,9 @@ LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname, struct sockaddr *address, int addrlen) LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_endpoint *ep, struct sock *sk, struct sock *newsk) +LSM_HOOK(int, 0, gtp_dev_add, void **security) +LSM_HOOK(int, 0, gtp_dev_del, void *security) +LSM_HOOK(int, 0, gtp_dev_cmd, void *security, enum gtp_genl_cmds cmd) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9e2e3e637..3d6888d51 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -982,6 +982,22 @@ * This hook can be used by the module to update any security state * associated with the TUN device's security structure. * @security pointer to the TUN devices's security structure. + * @gtp_dev_add: + * This hook allows a module to allocate a security structure for a GTP + * device. + * @security pointer to a security structure pointer. + * Returns a zero on success, negative values on failure. + * @gtp_dev_del: + * This hook allows a module to free the security structure for a GTP + * device. + * @security pointer to the GTP device's security structure. + * Returns a zero on success, negative values on failure. + * @gtp_dev_cmd: + * This hook allows a module to free the security structure for a GTP + * device. + * @security pointer to the GTP device's security structure. + * @cmd contains the GTP command. + * Returns a zero on success, negative values on failure. * * Security hooks for SCTP * diff --git a/include/linux/security.h b/include/linux/security.h index 0a0a03b36..67ff43afa 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -30,6 +30,7 @@ #include #include #include +#include struct linux_binprm; struct cred; @@ -1365,6 +1366,9 @@ int security_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address, int addrlen); void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, struct sock *newsk); +int security_gtp_dev_add(void **security); +int security_gtp_dev_del(void *security); +int security_gtp_dev_cmd(void *security, enum gtp_genl_cmds cmd); #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct sock *sock, @@ -1582,6 +1586,21 @@ static inline void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *newsk) { } + +static inline int security_gtp_dev_add(void **security) +{ + return 0; +} + +static inline int security_gtp_dev_del(void *security) +{ + return 0; +} + +static inline int security_gtp_dev_cmd(void *security, enum gtp_genl_cmds cmd) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND diff --git a/security/security.c b/security/security.c index 70a7ad357..63b656848 100644 --- a/security/security.c +++ b/security/security.c @@ -2304,6 +2304,24 @@ void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, } EXPORT_SYMBOL(security_sctp_sk_clone); +int security_gtp_dev_add(void **security) +{ + return call_int_hook(gtp_dev_add, 0, security); +} +EXPORT_SYMBOL(security_gtp_dev_add); + +int security_gtp_dev_del(void *security) +{ + return call_int_hook(gtp_dev_del, 0, security); +} +EXPORT_SYMBOL(security_gtp_dev_del); + +int security_gtp_dev_cmd(void *security, enum gtp_genl_cmds cmd) +{ + return call_int_hook(gtp_dev_cmd, 0, security, cmd); +} +EXPORT_SYMBOL(security_gtp_dev_cmd); + #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -- 2.26.2 From richard_c_haines at btinternet.com Sat Oct 17 05:01:08 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Sat, 17 Oct 2020 05:01:08 -0000 Subject: [RFC PATCH 2/3] gtp: Add LSM hooks to GPRS Tunneling Protocol (GTP) In-Reply-To: <20200924085102.5960-1-richard_c_haines@btinternet.com> References: <20200924085102.5960-1-richard_c_haines@btinternet.com> Message-ID: <20200924085102.5960-3-richard_c_haines@btinternet.com> Add security hooks to allow security modules to exercise access control over GTP. Signed-off-by: Richard Haines --- drivers/net/gtp.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 21640a035..ee00b12ab 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -73,6 +73,8 @@ struct gtp_dev { unsigned int hash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; + + void *security; }; static unsigned int gtp_net_id __read_mostly; @@ -663,6 +665,12 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); + err = security_gtp_dev_add(>p->security); + pr_debug("security_gtp_dev_add() ptr: %p err: %d\n", + gtp->security, err); + if (err < 0) + return err; + err = gtp_encap_enable(gtp, data); if (err < 0) return err; @@ -705,7 +713,15 @@ 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_del(gtp->security); + pr_debug("security_gtp_dev_del() ptr: %p err: %d\n", + gtp->security, err); + if (err < 0) { + pr_err("Failed security_gtp_dev_del_link() 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 +1092,12 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } + err = security_gtp_dev_cmd(gtp->security, GTP_CMD_NEWPDP); + pr_debug("security_gtp_dev_cmd(GTP_CMD_NEWPDP) ptr: %p err: %d\n", + gtp->security, err); + if (err < 0) + goto out_unlock; + if (version == GTP_V0) sk = gtp->sk0; else if (version == GTP_V1) @@ -1139,6 +1161,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 +1175,13 @@ 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->security, GTP_CMD_DELPDP); + pr_debug("security_gtp_dev_cmd(GTP_CMD_DELPDP) ptr: %p err: %d\n", + gtp->security, err); + 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 +1238,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 +1252,13 @@ 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->security, GTP_CMD_GETPDP); + pr_debug("security_gtp_dev_cmd(GTP_CMD_GETPDP) ptr: %p err: %d\n", + gtp->security, err); + if (err < 0) + goto err_unlock; + skb2 = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (skb2 == NULL) { err = -ENOMEM; @@ -1250,6 +1288,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 +1302,14 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, else last_gtp = NULL; + err = security_gtp_dev_cmd(gtp->security, GTP_CMD_GETPDP); + pr_debug("security_gtp_dev_cmd(GTP_CMD_GETPDP) ptr: %p err: %d\n", + gtp->security, err); + 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], -- 2.26.2 From richard_c_haines at btinternet.com Sat Oct 17 12:52:02 2020 From: richard_c_haines at btinternet.com (Richard Haines) Date: Sat, 17 Oct 2020 12:52:02 -0000 Subject: [RFC PATCH 3/3] selinux: Add SELinux GTP support In-Reply-To: <20200924085102.5960-1-richard_c_haines@btinternet.com> References: <20200924085102.5960-1-richard_c_haines@btinternet.com> Message-ID: <20200924085102.5960-4-richard_c_haines@btinternet.com> The SELinux GTP implementation is explained in: Documentation/security/GTP.rst Signed-off-by: Richard Haines --- Documentation/security/GTP.rst | 59 ++++++++++++++++++++++++++ security/selinux/hooks.c | 64 +++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 + security/selinux/include/objsec.h | 4 ++ 4 files changed, 129 insertions(+) diff --git a/Documentation/security/GTP.rst b/Documentation/security/GTP.rst index e307d0b59..55e41ecd0 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_del() 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_add() ~~~~~~~~~~~~~~~~~~~~~~ @@ -37,3 +40,59 @@ 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_add(>p->security) + security_gtp_dev_del(gtp->security) + security_gtp_dev_cmd(gtp->security, cmd) + + +security_gtp_dev_add() +~~~~~~~~~~~~~~~~~~~~~~ +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. + + +security_gtp_dev_del() +~~~~~~~~~~~~~~~~~~~~~~ +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. + + +security_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 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. + + 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..74b2bea87 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5520,6 +5520,67 @@ static int selinux_tun_dev_open(void *security) return 0; } +static int selinux_gtp_dev_add(void **security) +{ + struct gtp_security_struct *gtpsec = NULL; + 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; + *security = gtpsec; + + return 0; +} + +static int selinux_gtp_dev_del(void *security) +{ + struct gtp_security_struct *gtpsec = 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; + + kfree(security); + + return 0; +} + +static int selinux_gtp_dev_cmd(void *security, enum gtp_genl_cmds cmd) +{ + struct gtp_security_struct *gtpsec = 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 +7191,9 @@ 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_add, selinux_gtp_dev_add), + LSM_HOOK_INIT(gtp_dev_del, selinux_gtp_dev_del), + 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, 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) { -- 2.26.2 From ejeakaz at gmail.com Tue Oct 20 19:18:52 2020 From: ejeakaz at gmail.com (Jean-Marc Katembwe) Date: Tue, 20 Oct 2020 21:18:52 +0200 Subject: IPv6 PDP type support Message-ID: Hi, I would like to know if the current OsmoSGSN version can support IPv6 PDP type. Thanks, Jean-Marc -------------- next part -------------- An HTML attachment was scrubbed... URL: From laforge at osmocom.org Wed Oct 21 08:39:24 2020 From: laforge at osmocom.org (Harald Welte) Date: Wed, 21 Oct 2020 10:39:24 +0200 Subject: IPv6 PDP type support In-Reply-To: References: Message-ID: <20201021083924.GF35229@nataraja> Dear Jean-Marc, On Tue, Oct 20, 2020 at 09:18:52PM +0200, Jean-Marc Katembwe wrote: > I would like to know if the current OsmoSGSN version can support IPv6 PDP > type. Yes,it does. Unfortunately it is not explicitly mentioned in the user manual at https://ftp.osmocom.org/docs/latest/osmosgsn-usermanual.pdf but can be seeon only implicitly in the VTY reference manual at https://ftp.osmocom.org/docs/latest/osmoggsn-vty-reference.pdf There are automatic tests that execute every night, go to https://jenkins.osmocom.org/jenkins/view/TTCN3/job/ttcn3-ggsn-test/test_results_analyzer/ and click on 'expand all', where you can see various 'pdp6' and 'pdp46' test cases all passing. The same is true for the latest released/tagged version, see https://jenkins.osmocom.org/jenkins/view/TTCN3/job/ttcn3-ggsn-test-latest/test_results_analyzer/ Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From fujiwara.masahiro at gmail.com Sat Oct 24 15:42:33 2020 From: fujiwara.masahiro at gmail.com (Masahiro Fujiwara) Date: Sat, 24 Oct 2020 15:42:33 +0000 Subject: [PATCH net] gtp: fix an use-before-init in gtp_newlink() Message-ID: <20201024154233.4024-1-fujiwara.masahiro@gmail.com> *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer sends GTP packets while creating new GTP device. RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] Call Trace: gtp_encap_recv+0xc2/0x2e0 [gtp] ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] udp_queue_rcv_one_skb+0x1fe/0x530 udp_queue_rcv_skb+0x40/0x1b0 udp_unicast_rcv_skb.isra.0+0x78/0x90 __udp4_lib_rcv+0x5af/0xc70 udp_rcv+0x1a/0x20 ip_protocol_deliver_rcu+0xc5/0x1b0 ip_local_deliver_finish+0x48/0x50 ip_local_deliver+0xe5/0xf0 ? ip_protocol_deliver_rcu+0x1b0/0x1b0 gtp_encap_enable() should be called after gtp_hastable_new() otherwise *_pdp_find() will access the uninitialized hash table. Fixes: 1e3a3abd8 ("gtp: make GTP sockets in gtp_newlink optional") Signed-off-by: Masahiro Fujiwara --- drivers/net/gtp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 8e47d0112e5d..6c56337b02a3 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); - err = gtp_encap_enable(gtp, data); - if (err < 0) - return err; - if (!data[IFLA_GTP_PDP_HASHSIZE]) { hashsize = 1024; } else { @@ -676,13 +672,18 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, } err = gtp_hashtable_new(gtp, hashsize); + if (err < 0) { + return err; + } + + err = gtp_encap_enable(gtp, data); if (err < 0) goto out_encap; err = register_netdevice(dev); if (err < 0) { netdev_dbg(dev, "failed to register new netdev %d\n", err); - goto out_hashtable; + goto out_encap; } gn = net_generic(dev_net(dev), gtp_net_id); @@ -693,11 +694,10 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, return 0; -out_hashtable: - kfree(gtp->addr_hash); - kfree(gtp->tid_hash); out_encap: gtp_encap_disable(gtp); + kfree(gtp->addr_hash); + kfree(gtp->tid_hash); return err; } -- 2.24.3 From kuba at kernel.org Sun Oct 25 21:05:50 2020 From: kuba at kernel.org (Jakub Kicinski) Date: Sun, 25 Oct 2020 14:05:50 -0700 Subject: [PATCH net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201024154233.4024-1-fujiwara.masahiro@gmail.com> References: <20201024154233.4024-1-fujiwara.masahiro@gmail.com> Message-ID: <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> On Sat, 24 Oct 2020 15:42:33 +0000 Masahiro Fujiwara wrote: > *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer > sends GTP packets while creating new GTP device. > > RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] > > Call Trace: > > gtp_encap_recv+0xc2/0x2e0 [gtp] > ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] > udp_queue_rcv_one_skb+0x1fe/0x530 > udp_queue_rcv_skb+0x40/0x1b0 > udp_unicast_rcv_skb.isra.0+0x78/0x90 > __udp4_lib_rcv+0x5af/0xc70 > udp_rcv+0x1a/0x20 > ip_protocol_deliver_rcu+0xc5/0x1b0 > ip_local_deliver_finish+0x48/0x50 > ip_local_deliver+0xe5/0xf0 > ? ip_protocol_deliver_rcu+0x1b0/0x1b0 > > gtp_encap_enable() should be called after gtp_hastable_new() otherwise > *_pdp_find() will access the uninitialized hash table. Looks good, minor nits: - is the time zone broken on your system? Looks like your email has arrived with the date far in the past, so the build systems have missed it. Could you double check the time on your system? > Fixes: 1e3a3abd8 ("gtp: make GTP sockets in gtp_newlink optional") The hash looks short, should be at lest 12 chars: Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") > Signed-off-by: Masahiro Fujiwara > diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c > index 8e47d0112e5d..6c56337b02a3 100644 > --- a/drivers/net/gtp.c > +++ b/drivers/net/gtp.c > @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > gtp = netdev_priv(dev); > > - err = gtp_encap_enable(gtp, data); > - if (err < 0) > - return err; > - > if (!data[IFLA_GTP_PDP_HASHSIZE]) { > hashsize = 1024; > } else { > @@ -676,13 +672,18 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > } > > err = gtp_hashtable_new(gtp, hashsize); > + if (err < 0) { > + return err; > + } no need for braces around single statement > + > + err = gtp_encap_enable(gtp, data); > if (err < 0) > goto out_encap; > > err = register_netdevice(dev); > if (err < 0) { > netdev_dbg(dev, "failed to register new netdev %d\n", err); > - goto out_hashtable; > + goto out_encap; > } > > gn = net_generic(dev_net(dev), gtp_net_id); > @@ -693,11 +694,10 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > return 0; > > -out_hashtable: > - kfree(gtp->addr_hash); > - kfree(gtp->tid_hash); > out_encap: > gtp_encap_disable(gtp); I'd personally move the out_hashtable: label here and keep it, just for clarity. Otherwise reader has to double check that gtp_encap_disable() can be safely called before gtp_encap_enable(). Also gtp_encap_disable() could change in the future breaking this assumption. > + kfree(gtp->addr_hash); > + kfree(gtp->tid_hash); > return err; > } > From fujiwara.masahiro at gmail.com Mon Oct 26 06:37:48 2020 From: fujiwara.masahiro at gmail.com (Masahiro Fujiwara) Date: Mon, 26 Oct 2020 15:37:48 +0900 Subject: [PATCH net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> References: <20201024154233.4024-1-fujiwara.masahiro@gmail.com> <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> Message-ID: Hi, Thanks for the review. Will send a new patch with the fixes soon. ---- Fujiwara On Mon, Oct 26, 2020 at 6:05 AM Jakub Kicinski wrote: > > On Sat, 24 Oct 2020 15:42:33 +0000 Masahiro Fujiwara wrote: > > *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer > > sends GTP packets while creating new GTP device. > > > > RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] > > > > Call Trace: > > > > gtp_encap_recv+0xc2/0x2e0 [gtp] > > ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] > > udp_queue_rcv_one_skb+0x1fe/0x530 > > udp_queue_rcv_skb+0x40/0x1b0 > > udp_unicast_rcv_skb.isra.0+0x78/0x90 > > __udp4_lib_rcv+0x5af/0xc70 > > udp_rcv+0x1a/0x20 > > ip_protocol_deliver_rcu+0xc5/0x1b0 > > ip_local_deliver_finish+0x48/0x50 > > ip_local_deliver+0xe5/0xf0 > > ? ip_protocol_deliver_rcu+0x1b0/0x1b0 > > > > gtp_encap_enable() should be called after gtp_hastable_new() otherwise > > *_pdp_find() will access the uninitialized hash table. > > Looks good, minor nits: > > - is the time zone broken on your system? Looks like your email has > arrived with the date far in the past, so the build systems have > missed it. Could you double check the time on your system? > > > Fixes: 1e3a3abd8 ("gtp: make GTP sockets in gtp_newlink optional") > > The hash looks short, should be at lest 12 chars: > > Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") > > > Signed-off-by: Masahiro Fujiwara > > > diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c > > index 8e47d0112e5d..6c56337b02a3 100644 > > --- a/drivers/net/gtp.c > > +++ b/drivers/net/gtp.c > > @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > > > gtp = netdev_priv(dev); > > > > - err = gtp_encap_enable(gtp, data); > > - if (err < 0) > > - return err; > > - > > if (!data[IFLA_GTP_PDP_HASHSIZE]) { > > hashsize = 1024; > > } else { > > @@ -676,13 +672,18 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > } > > > > err = gtp_hashtable_new(gtp, hashsize); > > + if (err < 0) { > > + return err; > > + } > > no need for braces around single statement > > > + > > + err = gtp_encap_enable(gtp, data); > > if (err < 0) > > goto out_encap; > > > > err = register_netdevice(dev); > > if (err < 0) { > > netdev_dbg(dev, "failed to register new netdev %d\n", err); > > - goto out_hashtable; > > + goto out_encap; > > } > > > > gn = net_generic(dev_net(dev), gtp_net_id); > > @@ -693,11 +694,10 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > > > return 0; > > > > -out_hashtable: > > - kfree(gtp->addr_hash); > > - kfree(gtp->tid_hash); > > out_encap: > > gtp_encap_disable(gtp); > > I'd personally move the out_hashtable: label here and keep it, just for > clarity. Otherwise reader has to double check that gtp_encap_disable() > can be safely called before gtp_encap_enable(). > > Also gtp_encap_disable() could change in the future breaking this > assumption. > > > + kfree(gtp->addr_hash); > > + kfree(gtp->tid_hash); > > return err; > > } > > > From fujiwara.masahiro at gmail.com Mon Oct 26 07:22:27 2020 From: fujiwara.masahiro at gmail.com (Masahiro Fujiwara) Date: Mon, 26 Oct 2020 16:22:27 +0900 Subject: [PATCH v2 net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> References: <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> Message-ID: <20201026072227.7280-1-fujiwara.masahiro@gmail.com> *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer sends GTP packets while creating new GTP device. RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] Call Trace: gtp_encap_recv+0xc2/0x2e0 [gtp] ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] udp_queue_rcv_one_skb+0x1fe/0x530 udp_queue_rcv_skb+0x40/0x1b0 udp_unicast_rcv_skb.isra.0+0x78/0x90 __udp4_lib_rcv+0x5af/0xc70 udp_rcv+0x1a/0x20 ip_protocol_deliver_rcu+0xc5/0x1b0 ip_local_deliver_finish+0x48/0x50 ip_local_deliver+0xe5/0xf0 ? ip_protocol_deliver_rcu+0x1b0/0x1b0 gtp_encap_enable() should be called after gtp_hastable_new() otherwise *_pdp_find() will access the uninitialized hash table. Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") Signed-off-by: Masahiro Fujiwara --- v2: - leave out_hashtable: label for clarity (Jakub). - fix code and comment styles. drivers/net/gtp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 8e47d0112e5d..07cb6d9495e8 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); - err = gtp_encap_enable(gtp, data); - if (err < 0) - return err; - if (!data[IFLA_GTP_PDP_HASHSIZE]) { hashsize = 1024; } else { @@ -676,13 +672,17 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, } err = gtp_hashtable_new(gtp, hashsize); + if (err < 0) + return err; + + err = gtp_encap_enable(gtp, data); if (err < 0) goto out_encap; err = register_netdevice(dev); if (err < 0) { netdev_dbg(dev, "failed to register new netdev %d\n", err); - goto out_hashtable; + goto out_encap; } gn = net_generic(dev_net(dev), gtp_net_id); @@ -693,11 +693,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, return 0; +out_encap: + gtp_encap_disable(gtp); out_hashtable: kfree(gtp->addr_hash); kfree(gtp->tid_hash); -out_encap: - gtp_encap_disable(gtp); return err; } -- 2.24.3 From kuba at kernel.org Mon Oct 26 18:46:33 2020 From: kuba at kernel.org (Jakub Kicinski) Date: Mon, 26 Oct 2020 11:46:33 -0700 Subject: [PATCH v2 net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201026072227.7280-1-fujiwara.masahiro@gmail.com> References: <20201025140550.1e29f770@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> <20201026072227.7280-1-fujiwara.masahiro@gmail.com> Message-ID: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> On Mon, 26 Oct 2020 16:22:27 +0900 Masahiro Fujiwara wrote: > v2: > - leave out_hashtable: label for clarity (Jakub). > - fix code and comment styles. Thanks! > diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c > index 8e47d0112e5d..07cb6d9495e8 100644 > --- a/drivers/net/gtp.c > +++ b/drivers/net/gtp.c > @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > > gtp = netdev_priv(dev); > > - err = gtp_encap_enable(gtp, data); > - if (err < 0) > - return err; > - > if (!data[IFLA_GTP_PDP_HASHSIZE]) { > hashsize = 1024; > } else { > @@ -676,13 +672,17 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, > } > > err = gtp_hashtable_new(gtp, hashsize); > + if (err < 0) > + return err; > + > + err = gtp_encap_enable(gtp, data); > if (err < 0) > goto out_encap; This needs to say goto out_hashtable; now. From fujiwara.masahiro at gmail.com Tue Oct 27 11:30:21 2020 From: fujiwara.masahiro at gmail.com (Masahiro Fujiwara) Date: Tue, 27 Oct 2020 20:30:21 +0900 Subject: [PATCH v3] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> References: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> Message-ID: <20201027113021.3581-1-fujiwara.masahiro@gmail.com> *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer sends GTP packets while creating new GTP device. RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] Call Trace: gtp_encap_recv+0xc2/0x2e0 [gtp] ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] udp_queue_rcv_one_skb+0x1fe/0x530 udp_queue_rcv_skb+0x40/0x1b0 udp_unicast_rcv_skb.isra.0+0x78/0x90 __udp4_lib_rcv+0x5af/0xc70 udp_rcv+0x1a/0x20 ip_protocol_deliver_rcu+0xc5/0x1b0 ip_local_deliver_finish+0x48/0x50 ip_local_deliver+0xe5/0xf0 ? ip_protocol_deliver_rcu+0x1b0/0x1b0 gtp_encap_enable() should be called after gtp_hastable_new() otherwise *_pdp_find() will access the uninitialized hash table. v2: - Leave out_hashtable: label for clarity (Jakub). - Fix code and comment styles. Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") Signed-off-by: Masahiro Fujiwara --- v3: - Fix goto err label. drivers/net/gtp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 8e47d0112e5d..10f910f8cbe5 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); - err = gtp_encap_enable(gtp, data); - if (err < 0) - return err; - if (!data[IFLA_GTP_PDP_HASHSIZE]) { hashsize = 1024; } else { @@ -677,12 +673,16 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, err = gtp_hashtable_new(gtp, hashsize); if (err < 0) - goto out_encap; + return err; + + err = gtp_encap_enable(gtp, data); + if (err < 0) + goto out_hashtable; err = register_netdevice(dev); if (err < 0) { netdev_dbg(dev, "failed to register new netdev %d\n", err); - goto out_hashtable; + goto out_encap; } gn = net_generic(dev_net(dev), gtp_net_id); @@ -693,11 +693,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, return 0; +out_encap: + gtp_encap_disable(gtp); out_hashtable: kfree(gtp->addr_hash); kfree(gtp->tid_hash); -out_encap: - gtp_encap_disable(gtp); return err; } -- 2.24.3 From fujiwara.masahiro at gmail.com Tue Oct 27 11:48:46 2020 From: fujiwara.masahiro at gmail.com (Masahiro Fujiwara) Date: Tue, 27 Oct 2020 20:48:46 +0900 Subject: [PATCH v3 net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> References: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> Message-ID: <20201027114846.3924-1-fujiwara.masahiro@gmail.com> *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer sends GTP packets while creating new GTP device. RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] Call Trace: gtp_encap_recv+0xc2/0x2e0 [gtp] ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] udp_queue_rcv_one_skb+0x1fe/0x530 udp_queue_rcv_skb+0x40/0x1b0 udp_unicast_rcv_skb.isra.0+0x78/0x90 __udp4_lib_rcv+0x5af/0xc70 udp_rcv+0x1a/0x20 ip_protocol_deliver_rcu+0xc5/0x1b0 ip_local_deliver_finish+0x48/0x50 ip_local_deliver+0xe5/0xf0 ? ip_protocol_deliver_rcu+0x1b0/0x1b0 gtp_encap_enable() should be called after gtp_hastable_new() otherwise *_pdp_find() will access the uninitialized hash table. Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") Signed-off-by: Masahiro Fujiwara --- v3: - Fix goto err label. drivers/net/gtp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 8e47d0112e5d..10f910f8cbe5 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -663,10 +663,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, gtp = netdev_priv(dev); - err = gtp_encap_enable(gtp, data); - if (err < 0) - return err; - if (!data[IFLA_GTP_PDP_HASHSIZE]) { hashsize = 1024; } else { @@ -677,12 +673,16 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, err = gtp_hashtable_new(gtp, hashsize); if (err < 0) - goto out_encap; + return err; + + err = gtp_encap_enable(gtp, data); + if (err < 0) + goto out_hashtable; err = register_netdevice(dev); if (err < 0) { netdev_dbg(dev, "failed to register new netdev %d\n", err); - goto out_hashtable; + goto out_encap; } gn = net_generic(dev_net(dev), gtp_net_id); @@ -693,11 +693,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, return 0; +out_encap: + gtp_encap_disable(gtp); out_hashtable: kfree(gtp->addr_hash); kfree(gtp->tid_hash); -out_encap: - gtp_encap_disable(gtp); return err; } -- 2.24.3 From kuba at kernel.org Thu Oct 29 16:46:39 2020 From: kuba at kernel.org (Jakub Kicinski) Date: Thu, 29 Oct 2020 09:46:39 -0700 Subject: [PATCH v3 net] gtp: fix an use-before-init in gtp_newlink() In-Reply-To: <20201027114846.3924-1-fujiwara.masahiro@gmail.com> References: <20201026114633.1b2628ae@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> <20201027114846.3924-1-fujiwara.masahiro@gmail.com> Message-ID: <20201029094639.10d74c47@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com> On Tue, 27 Oct 2020 20:48:46 +0900 Masahiro Fujiwara wrote: > *_pdp_find() from gtp_encap_recv() would trigger a crash when a peer > sends GTP packets while creating new GTP device. > > RIP: 0010:gtp1_pdp_find.isra.0+0x68/0x90 [gtp] > > Call Trace: > > gtp_encap_recv+0xc2/0x2e0 [gtp] > ? gtp1_pdp_find.isra.0+0x90/0x90 [gtp] > udp_queue_rcv_one_skb+0x1fe/0x530 > udp_queue_rcv_skb+0x40/0x1b0 > udp_unicast_rcv_skb.isra.0+0x78/0x90 > __udp4_lib_rcv+0x5af/0xc70 > udp_rcv+0x1a/0x20 > ip_protocol_deliver_rcu+0xc5/0x1b0 > ip_local_deliver_finish+0x48/0x50 > ip_local_deliver+0xe5/0xf0 > ? ip_protocol_deliver_rcu+0x1b0/0x1b0 > > gtp_encap_enable() should be called after gtp_hastable_new() otherwise > *_pdp_find() will access the uninitialized hash table. > > Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional") > Signed-off-by: Masahiro Fujiwara Applied, thank you!