Merge tag 'selinux-pr-20250323' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore:

 - Add additional SELinux access controls for kernel file reads/loads

   The SELinux kernel file read/load access controls were never updated
   beyond the initial kernel module support, this pull request adds
   support for firmware, kexec, policies, and x.509 certificates.

 - Add support for wildcards in network interface names

   There are a number of userspace tools which auto-generate network
   interface names using some pattern of <XXXX>-<NN> where <XXXX> is a
   fixed string, e.g. "podman", and <NN> is a increasing counter.
   Supporting wildcards in the SELinux policy for network interfaces
   simplifies the policy associted with these interfaces.

 - Fix a potential problem in the kernel read file SELinux code

   SELinux should always check the file label in the
   security_kernel_read_file() LSM hook, regardless of if the file is
   being read in chunks. Unfortunately, the existing code only
   considered the file label on the first chunk; this pull request fixes
   this problem.

   There is more detail in the individual commit, but thankfully the
   existing code didn't expose a bug due to multi-stage reads only
   taking place in one driver, and that driver loading a file type that
   isn't targeted by the SELinux policy.

 - Fix the subshell error handling in the example policy loader

   Minor fix to SELinux example policy loader in scripts/selinux due to
   an undesired interaction with subshells and errexit.

* tag 'selinux-pr-20250323' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: get netif_wildcard policycap from policy instead of cache
  selinux: support wildcard network interface names
  selinux: Chain up tool resolving errors in install_policy.sh
  selinux: add permission checks for loading other kinds of kernel files
  selinux: always check the file label in selinux_kernel_read_file()
  selinux: fix spelling error
This commit is contained in:
Linus Torvalds
2025-03-25 15:52:32 -07:00
8 changed files with 79 additions and 25 deletions

View File

@@ -6,27 +6,24 @@ if [ `id -u` -ne 0 ]; then
exit 1
fi
SF=`which setfiles`
if [ $? -eq 1 ]; then
SF=`which setfiles` || {
echo "Could not find setfiles"
echo "Do you have policycoreutils installed?"
exit 1
fi
}
CP=`which checkpolicy`
if [ $? -eq 1 ]; then
CP=`which checkpolicy` || {
echo "Could not find checkpolicy"
echo "Do you have checkpolicy installed?"
exit 1
fi
}
VERS=`$CP -V | awk '{print $1}'`
ENABLED=`which selinuxenabled`
if [ $? -eq 1 ]; then
ENABLED=`which selinuxenabled` || {
echo "Could not find selinuxenabled"
echo "Do you have libselinux-utils installed?"
exit 1
fi
}
if selinuxenabled; then
echo "SELinux is already enabled"

View File

@@ -936,7 +936,7 @@ static void avc_flush(void)
spin_lock_irqsave(lock, flag);
/*
* With preemptable RCU, the outer spinlock does not
* With preemptible RCU, the outer spinlock does not
* prevent RCU grace periods from ending.
*/
rcu_read_lock();

View File

@@ -4099,7 +4099,7 @@ static int selinux_kernel_module_request(char *kmod_name)
SYSTEM__MODULE_REQUEST, &ad);
}
static int selinux_kernel_module_from_file(struct file *file)
static int selinux_kernel_load_from_file(struct file *file, u32 requested)
{
struct common_audit_data ad;
struct inode_security_struct *isec;
@@ -4107,12 +4107,8 @@ static int selinux_kernel_module_from_file(struct file *file)
u32 sid = current_sid();
int rc;
/* init_module */
if (file == NULL)
return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
SYSTEM__MODULE_LOAD, NULL);
/* finit_module */
return avc_has_perm(sid, sid, SECCLASS_SYSTEM, requested, NULL);
ad.type = LSM_AUDIT_DATA_FILE;
ad.u.file = file;
@@ -4125,8 +4121,7 @@ static int selinux_kernel_module_from_file(struct file *file)
}
isec = inode_security(file_inode(file));
return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
SYSTEM__MODULE_LOAD, &ad);
return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, requested, &ad);
}
static int selinux_kernel_read_file(struct file *file,
@@ -4135,9 +4130,30 @@ static int selinux_kernel_read_file(struct file *file,
{
int rc = 0;
BUILD_BUG_ON_MSG(READING_MAX_ID > 7,
"New kernel_read_file_id introduced; update SELinux!");
switch (id) {
case READING_FIRMWARE:
rc = selinux_kernel_load_from_file(file, SYSTEM__FIRMWARE_LOAD);
break;
case READING_MODULE:
rc = selinux_kernel_module_from_file(contents ? file : NULL);
rc = selinux_kernel_load_from_file(file, SYSTEM__MODULE_LOAD);
break;
case READING_KEXEC_IMAGE:
rc = selinux_kernel_load_from_file(file,
SYSTEM__KEXEC_IMAGE_LOAD);
break;
case READING_KEXEC_INITRAMFS:
rc = selinux_kernel_load_from_file(file,
SYSTEM__KEXEC_INITRAMFS_LOAD);
break;
case READING_POLICY:
rc = selinux_kernel_load_from_file(file, SYSTEM__POLICY_LOAD);
break;
case READING_X509_CERTIFICATE:
rc = selinux_kernel_load_from_file(file,
SYSTEM__X509_CERTIFICATE_LOAD);
break;
default:
break;
@@ -4150,9 +4166,31 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
{
int rc = 0;
BUILD_BUG_ON_MSG(LOADING_MAX_ID > 7,
"New kernel_load_data_id introduced; update SELinux!");
switch (id) {
case LOADING_FIRMWARE:
rc = selinux_kernel_load_from_file(NULL, SYSTEM__FIRMWARE_LOAD);
break;
case LOADING_MODULE:
rc = selinux_kernel_module_from_file(NULL);
rc = selinux_kernel_load_from_file(NULL, SYSTEM__MODULE_LOAD);
break;
case LOADING_KEXEC_IMAGE:
rc = selinux_kernel_load_from_file(NULL,
SYSTEM__KEXEC_IMAGE_LOAD);
break;
case LOADING_KEXEC_INITRAMFS:
rc = selinux_kernel_load_from_file(NULL,
SYSTEM__KEXEC_INITRAMFS_LOAD);
break;
case LOADING_POLICY:
rc = selinux_kernel_load_from_file(NULL,
SYSTEM__POLICY_LOAD);
break;
case LOADING_X509_CERTIFICATE:
rc = selinux_kernel_load_from_file(NULL,
SYSTEM__X509_CERTIFICATE_LOAD);
break;
default:
break;

View File

@@ -63,7 +63,9 @@ const struct security_class_mapping secclass_map[] = {
{ "process2", { "nnp_transition", "nosuid_transition", NULL } },
{ "system",
{ "ipc_info", "syslog_read", "syslog_mod", "syslog_console",
"module_request", "module_load", NULL } },
"module_request", "module_load", "firmware_load",
"kexec_image_load", "kexec_initramfs_load", "policy_load",
"x509_certificate_load", NULL } },
{ "capability", { COMMON_CAP_PERMS, NULL } },
{ "filesystem",
{ "mount", "remount", "unmount", "getattr", "relabelfrom",

View File

@@ -15,6 +15,7 @@ enum {
POLICYDB_CAP_IOCTL_SKIP_CLOEXEC,
POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT,
POLICYDB_CAP_NETLINK_XPERM,
POLICYDB_CAP_NETIF_WILDCARD,
__POLICYDB_CAP_MAX
};
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)

View File

@@ -18,6 +18,7 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = {
"ioctl_skip_cloexec",
"userspace_initial_context",
"netlink_xperm",
"netif_wildcard",
};
/* clang-format on */

View File

@@ -202,6 +202,12 @@ static inline bool selinux_policycap_netlink_xperm(void)
selinux_state.policycap[POLICYDB_CAP_NETLINK_XPERM]);
}
static inline bool selinux_policycap_netif_wildcard(void)
{
return READ_ONCE(
selinux_state.policycap[POLICYDB_CAP_NETIF_WILDCARD]);
}
struct selinux_policy_convert_data;
struct selinux_load_state {
@@ -301,7 +307,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid);
int security_netif_sid(char *name, u32 *if_sid);
int security_netif_sid(const char *name, u32 *if_sid);
int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid);

View File

@@ -46,6 +46,7 @@
#include <linux/in.h>
#include <linux/sched.h>
#include <linux/audit.h>
#include <linux/parser.h>
#include <linux/vmalloc.h>
#include <linux/lsm_hooks.h>
#include <net/netlabel.h>
@@ -2572,13 +2573,14 @@ out:
* @name: interface name
* @if_sid: interface SID
*/
int security_netif_sid(char *name, u32 *if_sid)
int security_netif_sid(const char *name, u32 *if_sid)
{
struct selinux_policy *policy;
struct policydb *policydb;
struct sidtab *sidtab;
int rc;
struct ocontext *c;
bool wildcard_support;
if (!selinux_initialized()) {
*if_sid = SECINITSID_NETIF;
@@ -2591,11 +2593,18 @@ retry:
policy = rcu_dereference(selinux_state.policy);
policydb = &policy->policydb;
sidtab = policy->sidtab;
wildcard_support = ebitmap_get_bit(&policydb->policycaps, POLICYDB_CAP_NETIF_WILDCARD);
c = policydb->ocontexts[OCON_NETIF];
while (c) {
if (strcmp(name, c->u.name) == 0)
break;
if (wildcard_support) {
if (match_wildcard(c->u.name, name))
break;
} else {
if (strcmp(c->u.name, name) == 0)
break;
}
c = c->next;
}