aboutsummaryrefslogtreecommitdiff
path: root/security/apparmor/policy_ns.c
diff options
context:
space:
mode:
authorLibravatar Linus Torvalds <torvalds@linux-foundation.org>2023-02-21 18:24:12 -0800
committerLibravatar Linus Torvalds <torvalds@linux-foundation.org>2023-02-21 18:24:12 -0800
commit5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 (patch)
treecc5c2d0a898769fd59549594fedb3ee6f84e59a0 /security/apparmor/policy_ns.c
downloadlinux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.tar.gz
linux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.zip
Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-nextgrafted
Pull networking updates from Jakub Kicinski: "Core: - Add dedicated kmem_cache for typical/small skb->head, avoid having to access struct page at kfree time, and improve memory use. - Introduce sysctl to set default RPS configuration for new netdevs. - Define Netlink protocol specification format which can be used to describe messages used by each family and auto-generate parsers. Add tools for generating kernel data structures and uAPI headers. - Expose all net/core sysctls inside netns. - Remove 4s sleep in netpoll if carrier is instantly detected on boot. - Add configurable limit of MDB entries per port, and port-vlan. - Continue populating drop reasons throughout the stack. - Retire a handful of legacy Qdiscs and classifiers. Protocols: - Support IPv4 big TCP (TSO frames larger than 64kB). - Add IP_LOCAL_PORT_RANGE socket option, to control local port range on socket by socket basis. - Track and report in procfs number of MPTCP sockets used. - Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path manager. - IPv6: don't check net.ipv6.route.max_size and rely on garbage collection to free memory (similarly to IPv4). - Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986). - ICMP: add per-rate limit counters. - Add support for user scanning requests in ieee802154. - Remove static WEP support. - Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate reporting. - WiFi 7 EHT channel puncturing support (client & AP). BPF: - Add a rbtree data structure following the "next-gen data structure" precedent set by recently added linked list, that is, by using kfunc + kptr instead of adding a new BPF map type. - Expose XDP hints via kfuncs with initial support for RX hash and timestamp metadata. - Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to better support decap on GRE tunnel devices not operating in collect metadata. - Improve x86 JIT's codegen for PROBE_MEM runtime error checks. - Remove the need for trace_printk_lock for bpf_trace_printk and bpf_trace_vprintk helpers. - Extend libbpf's bpf_tracing.h support for tracing arguments of kprobes/uprobes and syscall as a special case. - Significantly reduce the search time for module symbols by livepatch and BPF. - Enable cpumasks to be used as kptrs, which is useful for tracing programs tracking which tasks end up running on which CPUs in different time intervals. - Add support for BPF trampoline on s390x and riscv64. - Add capability to export the XDP features supported by the NIC. - Add __bpf_kfunc tag for marking kernel functions as kfuncs. - Add cgroup.memory=nobpf kernel parameter option to disable BPF memory accounting for container environments. Netfilter: - Remove the CLUSTERIP target. It has been marked as obsolete for years, and we still have WARN splats wrt races of the out-of-band /proc interface installed by this target. - Add 'destroy' commands to nf_tables. They are identical to the existing 'delete' commands, but do not return an error if the referenced object (set, chain, rule...) did not exist. Driver API: - Improve cpumask_local_spread() locality to help NICs set the right IRQ affinity on AMD platforms. - Separate C22 and C45 MDIO bus transactions more clearly. - Introduce new DCB table to control DSCP rewrite on egress. - Support configuration of Physical Layer Collision Avoidance (PLCA) Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of shared medium Ethernet. - Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing preemption of low priority frames by high priority frames. - Add support for controlling MACSec offload using netlink SET. - Rework devlink instance refcounts to allow registration and de-registration under the instance lock. Split the code into multiple files, drop some of the unnecessarily granular locks and factor out common parts of netlink operation handling. - Add TX frame aggregation parameters (for USB drivers). - Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning messages with notifications for debug. - Allow offloading of UDP NEW connections via act_ct. - Add support for per action HW stats in TC. - Support hardware miss to TC action (continue processing in SW from a specific point in the action chain). - Warn if old Wireless Extension user space interface is used with modern cfg80211/mac80211 drivers. Do not support Wireless Extensions for Wi-Fi 7 devices at all. Everyone should switch to using nl80211 interface instead. - Improve the CAN bit timing configuration. Use extack to return error messages directly to user space, update the SJW handling, including the definition of a new default value that will benefit CAN-FD controllers, by increasing their oscillator tolerance. New hardware / drivers: - Ethernet: - nVidia BlueField-3 support (control traffic driver) - Ethernet support for imx93 SoCs - Motorcomm yt8531 gigabit Ethernet PHY - onsemi NCN26000 10BASE-T1S PHY (with support for PLCA) - Microchip LAN8841 PHY (incl. cable diagnostics and PTP) - Amlogic gxl MDIO mux - WiFi: - RealTek RTL8188EU (rtl8xxxu) - Qualcomm Wi-Fi 7 devices (ath12k) - CAN: - Renesas R-Car V4H Drivers: - Bluetooth: - Set Per Platform Antenna Gain (PPAG) for Intel controllers. - Ethernet NICs: - Intel (1G, igc): - support TSN / Qbv / packet scheduling features of i226 model - Intel (100G, ice): - use GNSS subsystem instead of TTY - multi-buffer XDP support - extend support for GPIO pins to E823 devices - nVidia/Mellanox: - update the shared buffer configuration on PFC commands - implement PTP adjphase function for HW offset control - TC support for Geneve and GRE with VF tunnel offload - more efficient crypto key management method - multi-port eswitch support - Netronome/Corigine: - add DCB IEEE support - support IPsec offloading for NFP3800 - Freescale/NXP (enetc): - support XDP_REDIRECT for XDP non-linear buffers - improve reconfig, avoid link flap and waiting for idle - support MAC Merge layer - Other NICs: - sfc/ef100: add basic devlink support for ef100 - ionic: rx_push mode operation (writing descriptors via MMIO) - bnxt: use the auxiliary bus abstraction for RDMA - r8169: disable ASPM and reset bus in case of tx timeout - cpsw: support QSGMII mode for J721e CPSW9G - cpts: support pulse-per-second output - ngbe: add an mdio bus driver - usbnet: optimize usbnet_bh() by avoiding unnecessary queuing - r8152: handle devices with FW with NCM support - amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation - virtio-net: support multi buffer XDP - virtio/vsock: replace virtio_vsock_pkt with sk_buff - tsnep: XDP support - Ethernet high-speed switches: - nVidia/Mellanox (mlxsw): - add support for latency TLV (in FW control messages) - Microchip (sparx5): - separate explicit and implicit traffic forwarding rules, make the implicit rules always active - add support for egress DSCP rewrite - IS0 VCAP support (Ingress Classification) - IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS etc.) - ES2 VCAP support (Egress Access Control) - support for Per-Stream Filtering and Policing (802.1Q, 8.6.5.1) - Ethernet embedded switches: - Marvell (mv88e6xxx): - add MAB (port auth) offload support - enable PTP receive for mv88e6390 - NXP (ocelot): - support MAC Merge layer - support for the the vsc7512 internal copper phys - Microchip: - lan9303: convert to PHYLINK - lan966x: support TC flower filter statistics - lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x - lan937x: support Credit Based Shaper configuration - ksz9477: support Energy Efficient Ethernet - other: - qca8k: convert to regmap read/write API, use bulk operations - rswitch: Improve TX timestamp accuracy - Intel WiFi (iwlwifi): - EHT (Wi-Fi 7) rate reporting - STEP equalizer support: transfer some STEP (connection to radio on platforms with integrated wifi) related parameters from the BIOS to the firmware. - Qualcomm 802.11ax WiFi (ath11k): - IPQ5018 support - Fine Timing Measurement (FTM) responder role support - channel 177 support - MediaTek WiFi (mt76): - per-PHY LED support - mt7996: EHT (Wi-Fi 7) support - Wireless Ethernet Dispatch (WED) reset support - switch to using page pool allocator - RealTek WiFi (rtw89): - support new version of Bluetooth co-existance - Mobile: - rmnet: support TX aggregation" * tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits) page_pool: add a comment explaining the fragment counter usage net: ethtool: fix __ethtool_dev_mm_supported() implementation ethtool: pse-pd: Fix double word in comments xsk: add linux/vmalloc.h to xsk.c sefltests: netdevsim: wait for devlink instance after netns removal selftest: fib_tests: Always cleanup before exit net/mlx5e: Align IPsec ASO result memory to be as required by hardware net/mlx5e: TC, Set CT miss to the specific ct action instance net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG net/mlx5: Refactor tc miss handling to a single function net/mlx5: Kconfig: Make tc offload depend on tc skb extension net/sched: flower: Support hardware miss to tc action net/sched: flower: Move filter handle initialization earlier net/sched: cls_api: Support hardware miss to tc action net/sched: Rename user cookie and act cookie sfc: fix builds without CONFIG_RTC_LIB sfc: clean up some inconsistent indentings net/mlx4_en: Introduce flexible array to silence overflow warning net: lan966x: Fix possible deadlock inside PTP net/ulp: Remove redundant ->clone() test in inet_clone_ulp(). ...
Diffstat (limited to 'security/apparmor/policy_ns.c')
-rw-r--r--security/apparmor/policy_ns.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c
new file mode 100644
index 000000000..fd5b7afbc
--- /dev/null
+++ b/security/apparmor/policy_ns.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy manipulation functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ *
+ * AppArmor policy namespaces, allow for different sets of policies
+ * to be loaded for tasks within the namespace.
+ */
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "include/apparmor.h"
+#include "include/cred.h"
+#include "include/policy_ns.h"
+#include "include/label.h"
+#include "include/policy.h"
+
+/* kernel label */
+struct aa_label *kernel_t;
+
+/* root profile namespace */
+struct aa_ns *root_ns;
+const char *aa_hidden_ns_name = "---";
+
+/**
+ * aa_ns_visible - test if @view is visible from @curr
+ * @curr: namespace to treat as the parent (NOT NULL)
+ * @view: namespace to test if visible from @curr (NOT NULL)
+ * @subns: whether view of a subns is allowed
+ *
+ * Returns: true if @view is visible from @curr else false
+ */
+bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns)
+{
+ if (curr == view)
+ return true;
+
+ if (!subns)
+ return false;
+
+ for ( ; view; view = view->parent) {
+ if (view->parent == curr)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * aa_ns_name - Find the ns name to display for @view from @curr
+ * @curr: current namespace (NOT NULL)
+ * @view: namespace attempting to view (NOT NULL)
+ * @subns: are subns visible
+ *
+ * Returns: name of @view visible from @curr
+ */
+const char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns)
+{
+ /* if view == curr then the namespace name isn't displayed */
+ if (curr == view)
+ return "";
+
+ if (aa_ns_visible(curr, view, subns)) {
+ /* at this point if a ns is visible it is in a view ns
+ * thus the curr ns.hname is a prefix of its name.
+ * Only output the virtualized portion of the name
+ * Add + 2 to skip over // separating curr hname prefix
+ * from the visible tail of the views hname
+ */
+ return view->base.hname + strlen(curr->base.hname) + 2;
+ }
+
+ return aa_hidden_ns_name;
+}
+
+static struct aa_profile *alloc_unconfined(const char *name)
+{
+ struct aa_profile *profile;
+
+ profile = aa_alloc_null(NULL, name, GFP_KERNEL);
+ if (!profile)
+ return NULL;
+
+ profile->label.flags |= FLAG_IX_ON_NAME_ERROR |
+ FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED;
+ profile->mode = APPARMOR_UNCONFINED;
+
+ return profile;
+}
+
+/**
+ * alloc_ns - allocate, initialize and return a new namespace
+ * @prefix: parent namespace name (MAYBE NULL)
+ * @name: a preallocated name (NOT NULL)
+ *
+ * Returns: refcounted namespace or NULL on failure.
+ */
+static struct aa_ns *alloc_ns(const char *prefix, const char *name)
+{
+ struct aa_ns *ns;
+
+ ns = kzalloc(sizeof(*ns), GFP_KERNEL);
+ AA_DEBUG("%s(%p)\n", __func__, ns);
+ if (!ns)
+ return NULL;
+ if (!aa_policy_init(&ns->base, prefix, name, GFP_KERNEL))
+ goto fail_ns;
+
+ INIT_LIST_HEAD(&ns->sub_ns);
+ INIT_LIST_HEAD(&ns->rawdata_list);
+ mutex_init(&ns->lock);
+ init_waitqueue_head(&ns->wait);
+
+ /* released by aa_free_ns() */
+ ns->unconfined = alloc_unconfined("unconfined");
+ if (!ns->unconfined)
+ goto fail_unconfined;
+ /* ns and ns->unconfined share ns->unconfined refcount */
+ ns->unconfined->ns = ns;
+
+ atomic_set(&ns->uniq_null, 0);
+
+ aa_labelset_init(&ns->labels);
+
+ return ns;
+
+fail_unconfined:
+ aa_policy_destroy(&ns->base);
+fail_ns:
+ kfree_sensitive(ns);
+ return NULL;
+}
+
+/**
+ * aa_free_ns - free a profile namespace
+ * @ns: the namespace to free (MAYBE NULL)
+ *
+ * Requires: All references to the namespace must have been put, if the
+ * namespace was referenced by a profile confining a task,
+ */
+void aa_free_ns(struct aa_ns *ns)
+{
+ if (!ns)
+ return;
+
+ aa_policy_destroy(&ns->base);
+ aa_labelset_destroy(&ns->labels);
+ aa_put_ns(ns->parent);
+
+ ns->unconfined->ns = NULL;
+ aa_free_profile(ns->unconfined);
+ kfree_sensitive(ns);
+}
+
+/**
+ * aa_findn_ns - look up a profile namespace on the namespace list
+ * @root: namespace to search in (NOT NULL)
+ * @name: name of namespace to find (NOT NULL)
+ * @n: length of @name
+ *
+ * Returns: a refcounted namespace on the list, or NULL if no namespace
+ * called @name exists.
+ *
+ * refcount released by caller
+ */
+struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n)
+{
+ struct aa_ns *ns = NULL;
+
+ rcu_read_lock();
+ ns = aa_get_ns(__aa_findn_ns(&root->sub_ns, name, n));
+ rcu_read_unlock();
+
+ return ns;
+}
+
+/**
+ * aa_find_ns - look up a profile namespace on the namespace list
+ * @root: namespace to search in (NOT NULL)
+ * @name: name of namespace to find (NOT NULL)
+ *
+ * Returns: a refcounted namespace on the list, or NULL if no namespace
+ * called @name exists.
+ *
+ * refcount released by caller
+ */
+struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name)
+{
+ return aa_findn_ns(root, name, strlen(name));
+}
+
+/**
+ * __aa_lookupn_ns - lookup the namespace matching @hname
+ * @view: namespace to search in (NOT NULL)
+ * @hname: hierarchical ns name (NOT NULL)
+ * @n: length of @hname
+ *
+ * Requires: rcu_read_lock be held
+ *
+ * Returns: unrefcounted ns pointer or NULL if not found
+ *
+ * Do a relative name lookup, recursing through profile tree.
+ */
+struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n)
+{
+ struct aa_ns *ns = view;
+ const char *split;
+
+ for (split = strnstr(hname, "//", n); split;
+ split = strnstr(hname, "//", n)) {
+ ns = __aa_findn_ns(&ns->sub_ns, hname, split - hname);
+ if (!ns)
+ return NULL;
+
+ n -= split + 2 - hname;
+ hname = split + 2;
+ }
+
+ if (n)
+ return __aa_findn_ns(&ns->sub_ns, hname, n);
+ return NULL;
+}
+
+/**
+ * aa_lookupn_ns - look up a policy namespace relative to @view
+ * @view: namespace to search in (NOT NULL)
+ * @name: name of namespace to find (NOT NULL)
+ * @n: length of @name
+ *
+ * Returns: a refcounted namespace on the list, or NULL if no namespace
+ * called @name exists.
+ *
+ * refcount released by caller
+ */
+struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n)
+{
+ struct aa_ns *ns = NULL;
+
+ rcu_read_lock();
+ ns = aa_get_ns(__aa_lookupn_ns(view, name, n));
+ rcu_read_unlock();
+
+ return ns;
+}
+
+static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
+ struct dentry *dir)
+{
+ struct aa_ns *ns;
+ int error;
+
+ AA_BUG(!parent);
+ AA_BUG(!name);
+ AA_BUG(!mutex_is_locked(&parent->lock));
+
+ ns = alloc_ns(parent->base.hname, name);
+ if (!ns)
+ return ERR_PTR(-ENOMEM);
+ ns->level = parent->level + 1;
+ mutex_lock_nested(&ns->lock, ns->level);
+ error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir);
+ if (error) {
+ AA_ERROR("Failed to create interface for ns %s\n",
+ ns->base.name);
+ mutex_unlock(&ns->lock);
+ aa_free_ns(ns);
+ return ERR_PTR(error);
+ }
+ ns->parent = aa_get_ns(parent);
+ list_add_rcu(&ns->base.list, &parent->sub_ns);
+ /* add list ref */
+ aa_get_ns(ns);
+ mutex_unlock(&ns->lock);
+
+ return ns;
+}
+
+/**
+ * __aa_find_or_create_ns - create an ns, fail if it already exists
+ * @parent: the parent of the namespace being created
+ * @name: the name of the namespace
+ * @dir: if not null the dir to put the ns entries in
+ *
+ * Returns: the a refcounted ns that has been add or an ERR_PTR
+ */
+struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
+ struct dentry *dir)
+{
+ struct aa_ns *ns;
+
+ AA_BUG(!mutex_is_locked(&parent->lock));
+
+ /* try and find the specified ns */
+ /* released by caller */
+ ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
+ if (!ns)
+ ns = __aa_create_ns(parent, name, dir);
+ else
+ ns = ERR_PTR(-EEXIST);
+
+ /* return ref */
+ return ns;
+}
+
+/**
+ * aa_prepare_ns - find an existing or create a new namespace of @name
+ * @parent: ns to treat as parent
+ * @name: the namespace to find or add (NOT NULL)
+ *
+ * Returns: refcounted namespace or PTR_ERR if failed to create one
+ */
+struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name)
+{
+ struct aa_ns *ns;
+
+ mutex_lock_nested(&parent->lock, parent->level);
+ /* try and find the specified ns and if it doesn't exist create it */
+ /* released by caller */
+ ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
+ if (!ns)
+ ns = __aa_create_ns(parent, name, NULL);
+ mutex_unlock(&parent->lock);
+
+ /* return ref */
+ return ns;
+}
+
+static void __ns_list_release(struct list_head *head);
+
+/**
+ * destroy_ns - remove everything contained by @ns
+ * @ns: namespace to have it contents removed (NOT NULL)
+ */
+static void destroy_ns(struct aa_ns *ns)
+{
+ if (!ns)
+ return;
+
+ mutex_lock_nested(&ns->lock, ns->level);
+ /* release all profiles in this namespace */
+ __aa_profile_list_release(&ns->base.profiles);
+
+ /* release all sub namespaces */
+ __ns_list_release(&ns->sub_ns);
+
+ if (ns->parent) {
+ unsigned long flags;
+
+ write_lock_irqsave(&ns->labels.lock, flags);
+ __aa_proxy_redirect(ns_unconfined(ns),
+ ns_unconfined(ns->parent));
+ write_unlock_irqrestore(&ns->labels.lock, flags);
+ }
+ __aafs_ns_rmdir(ns);
+ mutex_unlock(&ns->lock);
+}
+
+/**
+ * __aa_remove_ns - remove a namespace and all its children
+ * @ns: namespace to be removed (NOT NULL)
+ *
+ * Requires: ns->parent->lock be held and ns removed from parent.
+ */
+void __aa_remove_ns(struct aa_ns *ns)
+{
+ /* remove ns from namespace list */
+ list_del_rcu(&ns->base.list);
+ destroy_ns(ns);
+ aa_put_ns(ns);
+}
+
+/**
+ * __ns_list_release - remove all profile namespaces on the list put refs
+ * @head: list of profile namespaces (NOT NULL)
+ *
+ * Requires: namespace lock be held
+ */
+static void __ns_list_release(struct list_head *head)
+{
+ struct aa_ns *ns, *tmp;
+
+ list_for_each_entry_safe(ns, tmp, head, base.list)
+ __aa_remove_ns(ns);
+
+}
+
+/**
+ * aa_alloc_root_ns - allocate the root profile namespace
+ *
+ * Returns: %0 on success else error
+ *
+ */
+int __init aa_alloc_root_ns(void)
+{
+ struct aa_profile *kernel_p;
+
+ /* released by aa_free_root_ns - used as list ref*/
+ root_ns = alloc_ns(NULL, "root");
+ if (!root_ns)
+ return -ENOMEM;
+
+ kernel_p = alloc_unconfined("kernel_t");
+ if (!kernel_p) {
+ destroy_ns(root_ns);
+ aa_free_ns(root_ns);
+ return -ENOMEM;
+ }
+ kernel_t = &kernel_p->label;
+ root_ns->unconfined->ns = aa_get_ns(root_ns);
+
+ return 0;
+}
+
+ /**
+ * aa_free_root_ns - free the root profile namespace
+ */
+void __init aa_free_root_ns(void)
+{
+ struct aa_ns *ns = root_ns;
+
+ root_ns = NULL;
+
+ aa_label_free(kernel_t);
+ destroy_ns(ns);
+ aa_put_ns(ns);
+}