mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-18 12:19:11 +08:00
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:
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user