summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig.hardening14
-rw-r--r--security/integrity/evm/evm_main.c17
-rw-r--r--security/integrity/ima/ima_appraise.c12
-rw-r--r--security/integrity/platform_certs/load_uefi.c2
-rw-r--r--security/keys/internal.h2
-rw-r--r--security/landlock/fs.c50
-rw-r--r--security/landlock/syscalls.c40
-rw-r--r--security/loadpin/Kconfig7
-rw-r--r--security/loadpin/loadpin.c22
-rw-r--r--security/lockdown/lockdown.c2
-rw-r--r--security/lsm_audit.c14
-rw-r--r--security/security.c9
-rw-r--r--security/selinux/hooks.c57
-rw-r--r--security/selinux/include/classmap.h4
-rw-r--r--security/selinux/selinuxfs.c15
-rw-r--r--security/selinux/ss/context.h17
-rw-r--r--security/selinux/ss/ebitmap.c21
-rw-r--r--security/selinux/ss/ebitmap.h18
-rw-r--r--security/selinux/ss/mls_types.h4
-rw-r--r--security/smack/smack.h9
-rw-r--r--security/smack/smack_lsm.c52
-rw-r--r--security/tomoyo/audit.c2
-rw-r--r--security/tomoyo/common.c2
-rw-r--r--security/tomoyo/file.c2
-rw-r--r--security/tomoyo/realpath.c9
25 files changed, 249 insertions, 154 deletions
diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
index bd2aabb2c60f..995bc42003e6 100644
--- a/security/Kconfig.hardening
+++ b/security/Kconfig.hardening
@@ -22,11 +22,17 @@ menu "Memory initialization"
config CC_HAS_AUTO_VAR_INIT_PATTERN
def_bool $(cc-option,-ftrivial-auto-var-init=pattern)
-config CC_HAS_AUTO_VAR_INIT_ZERO
- # GCC ignores the -enable flag, so we can test for the feature with
- # a single invocation using the flag, but drop it as appropriate in
- # the Makefile, depending on the presence of Clang.
+config CC_HAS_AUTO_VAR_INIT_ZERO_BARE
+ def_bool $(cc-option,-ftrivial-auto-var-init=zero)
+
+config CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER
+ # Clang 16 and later warn about using the -enable flag, but it
+ # is required before then.
def_bool $(cc-option,-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang)
+ depends on !CC_HAS_AUTO_VAR_INIT_ZERO_BARE
+
+config CC_HAS_AUTO_VAR_INIT_ZERO
+ def_bool CC_HAS_AUTO_VAR_INIT_ZERO_BARE || CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER
choice
prompt "Initialize kernel stack variables at function entry"
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 2e6fb6e2ffd2..23d484e05e6f 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -457,10 +457,21 @@ static int evm_xattr_acl_change(struct user_namespace *mnt_userns,
int rc;
/*
- * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact
- * on the inode mode (see posix_acl_equiv_mode()).
+ * An earlier comment here mentioned that the idmappings for
+ * ACL_{GROUP,USER} don't matter since EVM is only interested in the
+ * mode stored as part of POSIX ACLs. Nonetheless, if it must translate
+ * from the uapi POSIX ACL representation to the VFS internal POSIX ACL
+ * representation it should do so correctly. There's no guarantee that
+ * we won't change POSIX ACLs in a way that ACL_{GROUP,USER} matters
+ * for the mode at some point and it's difficult to keep track of all
+ * the LSM and integrity modules and what they do to POSIX ACLs.
+ *
+ * Frankly, EVM shouldn't try to interpret the uapi struct for POSIX
+ * ACLs it received. It requires knowledge that only the VFS is
+ * guaranteed to have.
*/
- acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len);
+ acl = vfs_set_acl_prepare(mnt_userns, i_user_ns(inode),
+ xattr_value, xattr_value_len);
if (IS_ERR_OR_NULL(acl))
return 1;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index bde74fcecee3..3e0fbbd99534 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -750,22 +750,26 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const struct evm_ima_xattr_data *xvalue = xattr_value;
int digsig = 0;
int result;
+ int err;
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len);
if (result == 1) {
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
return -EINVAL;
+
+ err = validate_hash_algo(dentry, xvalue, xattr_value_len);
+ if (err)
+ return err;
+
digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
} else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) {
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
}
if (result == 1 || evm_revalidate_status(xattr_name)) {
- result = validate_hash_algo(dentry, xvalue, xattr_value_len);
- if (result)
- return result;
-
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
+ if (result == 1)
+ result = 0;
}
return result;
}
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index 093894a640dc..b78753d27d8e 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -31,7 +31,7 @@ static const struct dmi_system_id uefi_skip_cert[] = {
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") },
- { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacMini8,1") },
+ { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "Macmini8,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 9b9cf3b6fcbb..3c1e7122076b 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -165,8 +165,6 @@ extern struct key *request_key_and_link(struct key_type *type,
extern bool lookup_user_key_possessed(const struct key *key,
const struct key_match_data *match_data);
-#define KEY_LOOKUP_CREATE 0x01
-#define KEY_LOOKUP_PARTIAL 0x02
extern long join_session_keyring(const char *name);
extern void key_change_session_keyring(struct callback_head *twork);
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index ec5a6247cd3e..64ed7665455f 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -150,6 +150,16 @@ retry:
/* clang-format on */
/*
+ * All access rights that are denied by default whether they are handled or not
+ * by a ruleset/layer. This must be ORed with all ruleset->fs_access_masks[]
+ * entries when we need to get the absolute handled access masks.
+ */
+/* clang-format off */
+#define ACCESS_INITIALLY_DENIED ( \
+ LANDLOCK_ACCESS_FS_REFER)
+/* clang-format on */
+
+/*
* @path: Should have been checked by get_path_from_fd().
*/
int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
@@ -167,7 +177,9 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
return -EINVAL;
/* Transforms relative access rights to absolute ones. */
- access_rights |= LANDLOCK_MASK_ACCESS_FS & ~ruleset->fs_access_masks[0];
+ access_rights |=
+ LANDLOCK_MASK_ACCESS_FS &
+ ~(ruleset->fs_access_masks[0] | ACCESS_INITIALLY_DENIED);
object = get_inode_object(d_backing_inode(path->dentry));
if (IS_ERR(object))
return PTR_ERR(object);
@@ -277,23 +289,12 @@ static inline bool is_nouser_or_private(const struct dentry *dentry)
static inline access_mask_t
get_handled_accesses(const struct landlock_ruleset *const domain)
{
- access_mask_t access_dom = 0;
- unsigned long access_bit;
-
- for (access_bit = 0; access_bit < LANDLOCK_NUM_ACCESS_FS;
- access_bit++) {
- size_t layer_level;
+ access_mask_t access_dom = ACCESS_INITIALLY_DENIED;
+ size_t layer_level;
- for (layer_level = 0; layer_level < domain->num_layers;
- layer_level++) {
- if (domain->fs_access_masks[layer_level] &
- BIT_ULL(access_bit)) {
- access_dom |= BIT_ULL(access_bit);
- break;
- }
- }
- }
- return access_dom;
+ for (layer_level = 0; layer_level < domain->num_layers; layer_level++)
+ access_dom |= domain->fs_access_masks[layer_level];
+ return access_dom & LANDLOCK_MASK_ACCESS_FS;
}
static inline access_mask_t
@@ -316,8 +317,13 @@ init_layer_masks(const struct landlock_ruleset *const domain,
for_each_set_bit(access_bit, &access_req,
ARRAY_SIZE(*layer_masks)) {
- if (domain->fs_access_masks[layer_level] &
- BIT_ULL(access_bit)) {
+ /*
+ * Artificially handles all initially denied by default
+ * access rights.
+ */
+ if (BIT_ULL(access_bit) &
+ (domain->fs_access_masks[layer_level] |
+ ACCESS_INITIALLY_DENIED)) {
(*layer_masks)[access_bit] |=
BIT_ULL(layer_level);
handled_accesses |= BIT_ULL(access_bit);
@@ -706,7 +712,7 @@ static inline access_mask_t maybe_remove(const struct dentry *const dentry)
* allowed accesses in @layer_masks_dom.
*
* This is similar to check_access_path_dual() but much simpler because it only
- * handles walking on the same mount point and only check one set of accesses.
+ * handles walking on the same mount point and only checks one set of accesses.
*
* Returns:
* - true if all the domain access rights are allowed for @dir;
@@ -857,10 +863,6 @@ static int current_check_refer_path(struct dentry *const old_dentry,
NULL, NULL);
}
- /* Backward compatibility: no reparenting support. */
- if (!(get_handled_accesses(dom) & LANDLOCK_ACCESS_FS_REFER))
- return -EXDEV;
-
access_request_parent1 |= LANDLOCK_ACCESS_FS_REFER;
access_request_parent2 |= LANDLOCK_ACCESS_FS_REFER;
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 735a0865ea11..2ca0ccbd905a 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -149,10 +149,10 @@ static const struct file_operations ruleset_fops = {
*
* Possible returned errors are:
*
- * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
- * - EINVAL: unknown @flags, or unknown access, or too small @size;
- * - E2BIG or EFAULT: @attr or @size inconsistencies;
- * - ENOMSG: empty &landlock_ruleset_attr.handled_access_fs.
+ * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
+ * - %EINVAL: unknown @flags, or unknown access, or too small @size;
+ * - %E2BIG or %EFAULT: @attr or @size inconsistencies;
+ * - %ENOMSG: empty &landlock_ruleset_attr.handled_access_fs.
*/
SYSCALL_DEFINE3(landlock_create_ruleset,
const struct landlock_ruleset_attr __user *const, attr,
@@ -280,7 +280,7 @@ out_fdput:
* @ruleset_fd: File descriptor tied to the ruleset that should be extended
* with the new rule.
* @rule_type: Identify the structure type pointed to by @rule_attr (only
- * LANDLOCK_RULE_PATH_BENEATH for now).
+ * %LANDLOCK_RULE_PATH_BENEATH for now).
* @rule_attr: Pointer to a rule (only of type &struct
* landlock_path_beneath_attr for now).
* @flags: Must be 0.
@@ -290,17 +290,17 @@ out_fdput:
*
* Possible returned errors are:
*
- * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
- * - EINVAL: @flags is not 0, or inconsistent access in the rule (i.e.
+ * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
+ * - %EINVAL: @flags is not 0, or inconsistent access in the rule (i.e.
* &landlock_path_beneath_attr.allowed_access is not a subset of the
* ruleset handled accesses);
- * - ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access);
- * - EBADF: @ruleset_fd is not a file descriptor for the current thread, or a
+ * - %ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access);
+ * - %EBADF: @ruleset_fd is not a file descriptor for the current thread, or a
* member of @rule_attr is not a file descriptor as expected;
- * - EBADFD: @ruleset_fd is not a ruleset file descriptor, or a member of
+ * - %EBADFD: @ruleset_fd is not a ruleset file descriptor, or a member of
* @rule_attr is not the expected file descriptor type;
- * - EPERM: @ruleset_fd has no write access to the underlying ruleset;
- * - EFAULT: @rule_attr inconsistency.
+ * - %EPERM: @ruleset_fd has no write access to the underlying ruleset;
+ * - %EFAULT: @rule_attr inconsistency.
*/
SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
const enum landlock_rule_type, rule_type,
@@ -378,20 +378,20 @@ out_put_ruleset:
* @flags: Must be 0.
*
* This system call enables to enforce a Landlock ruleset on the current
- * thread. Enforcing a ruleset requires that the task has CAP_SYS_ADMIN in its
+ * thread. Enforcing a ruleset requires that the task has %CAP_SYS_ADMIN in its
* namespace or is running with no_new_privs. This avoids scenarios where
* unprivileged tasks can affect the behavior of privileged children.
*
* Possible returned errors are:
*
- * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
- * - EINVAL: @flags is not 0.
- * - EBADF: @ruleset_fd is not a file descriptor for the current thread;
- * - EBADFD: @ruleset_fd is not a ruleset file descriptor;
- * - EPERM: @ruleset_fd has no read access to the underlying ruleset, or the
+ * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
+ * - %EINVAL: @flags is not 0.
+ * - %EBADF: @ruleset_fd is not a file descriptor for the current thread;
+ * - %EBADFD: @ruleset_fd is not a ruleset file descriptor;
+ * - %EPERM: @ruleset_fd has no read access to the underlying ruleset, or the
* current thread is not running with no_new_privs, or it doesn't have
- * CAP_SYS_ADMIN in its namespace.
- * - E2BIG: The maximum number of stacked rulesets is reached for the current
+ * %CAP_SYS_ADMIN in its namespace.
+ * - %E2BIG: The maximum number of stacked rulesets is reached for the current
* thread.
*/
SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
diff --git a/security/loadpin/Kconfig b/security/loadpin/Kconfig
index 70e7985b2561..6724eaba3d36 100644
--- a/security/loadpin/Kconfig
+++ b/security/loadpin/Kconfig
@@ -33,4 +33,9 @@ config SECURITY_LOADPIN_VERITY
on the LoadPin securityfs entry 'dm-verity'. The ioctl
expects a file descriptor of a file with verity digests as
parameter. The file must be located on the pinned root and
- contain a comma separated list of digests.
+ start with the line:
+
+ # LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS
+
+ This is followed by the verity digests, with one digest per
+ line.
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 6ab5f2bbf41f..de41621f4998 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -21,6 +21,8 @@
#include <linux/dm-verity-loadpin.h>
#include <uapi/linux/loadpin.h>
+#define VERITY_DIGEST_FILE_HEADER "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS"
+
static void report_load(const char *origin, struct file *file, char *operation)
{
char *cmdline, *pathname;
@@ -292,9 +294,21 @@ static int read_trusted_verity_root_digests(unsigned int fd)
p = strim(data);
while ((d = strsep(&p, "\n")) != NULL) {
- int len = strlen(d);
+ int len;
struct dm_verity_loadpin_trusted_root_digest *trd;
+ if (d == data) {
+ /* first line, validate header */
+ if (strcmp(d, VERITY_DIGEST_FILE_HEADER)) {
+ rc = -EPROTO;
+ goto err;
+ }
+
+ continue;
+ }
+
+ len = strlen(d);
+
if (len % 2) {
rc = -EPROTO;
goto err;
@@ -356,13 +370,11 @@ static long dm_verity_ioctl(struct file *filp, unsigned int cmd, unsigned long a
{
void __user *uarg = (void __user *)arg;
unsigned int fd;
- int rc;
switch (cmd) {
case LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS:
- rc = copy_from_user(&fd, uarg, sizeof(fd));
- if (rc)
- return rc;
+ if (copy_from_user(&fd, uarg, sizeof(fd)))
+ return -EFAULT;
return read_trusted_verity_root_digests(fd);
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 87cbdc64d272..a79b985e917e 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -63,7 +63,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
if (kernel_locked_down >= what) {
if (lockdown_reasons[what])
- pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
+ pr_notice_ratelimited("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
current->comm, lockdown_reasons[what]);
return -EPERM;
}
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 78a278f28e49..75cc3f8d2a42 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -44,9 +44,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
struct iphdr *ih;
ih = ip_hdr(skb);
- if (ih == NULL)
- return -EINVAL;
-
ad->u.net->v4info.saddr = ih->saddr;
ad->u.net->v4info.daddr = ih->daddr;
@@ -59,8 +56,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
switch (ih->protocol) {
case IPPROTO_TCP: {
struct tcphdr *th = tcp_hdr(skb);
- if (th == NULL)
- break;
ad->u.net->sport = th->source;
ad->u.net->dport = th->dest;
@@ -68,8 +63,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
}
case IPPROTO_UDP: {
struct udphdr *uh = udp_hdr(skb);
- if (uh == NULL)
- break;
ad->u.net->sport = uh->source;
ad->u.net->dport = uh->dest;
@@ -77,8 +70,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
}
case IPPROTO_DCCP: {
struct dccp_hdr *dh = dccp_hdr(skb);
- if (dh == NULL)
- break;
ad->u.net->sport = dh->dccph_sport;
ad->u.net->dport = dh->dccph_dport;
@@ -86,8 +77,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
}
case IPPROTO_SCTP: {
struct sctphdr *sh = sctp_hdr(skb);
- if (sh == NULL)
- break;
+
ad->u.net->sport = sh->source;
ad->u.net->dport = sh->dest;
break;
@@ -115,8 +105,6 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
__be16 frag_off;
ip6 = ipv6_hdr(skb);
- if (ip6 == NULL)
- return -EINVAL;
ad->u.net->v6info.saddr = ip6->saddr;
ad->u.net->v6info.daddr = ip6->daddr;
/* IPv6 can have several extension header before the Transport header
diff --git a/security/security.c b/security/security.c
index d8227531e2fd..8312b3bf1169 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1909,6 +1909,11 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode)
call_void_hook(task_to_inode, p, inode);
}
+int security_create_user_ns(const struct cred *cred)
+{
+ return call_int_hook(userns_create, 0, cred);
+}
+
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
return call_int_hook(ipc_permission, 0, ipcp, flag);
@@ -2660,4 +2665,8 @@ int security_uring_sqpoll(void)
{
return call_int_hook(uring_sqpoll, 0);
}
+int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+ return call_int_hook(uring_cmd, 0, ioucmd);
+}
#endif /* CONFIG_IO_URING */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c8168d19fb96..f553c370397e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -91,6 +91,7 @@
#include <uapi/linux/mount.h>
#include <linux/fsnotify.h>
#include <linux/fanotify.h>
+#include <linux/io_uring.h>
#include "avc.h"
#include "objsec.h"
@@ -4221,6 +4222,14 @@ static void selinux_task_to_inode(struct task_struct *p,
spin_unlock(&isec->lock);
}
+static int selinux_userns_create(const struct cred *cred)
+{
+ u32 sid = current_sid();
+
+ return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE,
+ USER_NAMESPACE__CREATE, NULL);
+}
+
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv4(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto)
@@ -5986,7 +5995,6 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
struct ipc_security_struct *isec;
struct common_audit_data ad;
u32 sid = current_sid();
- int rc;
isec = selinux_ipc(msq);
ipc_init_security(isec, SECCLASS_MSGQ);
@@ -5994,10 +6002,9 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->key;
- rc = avc_has_perm(&selinux_state,
- sid, isec->sid, SECCLASS_MSGQ,
- MSGQ__CREATE, &ad);
- return rc;
+ return avc_has_perm(&selinux_state,
+ sid, isec->sid, SECCLASS_MSGQ,
+ MSGQ__CREATE, &ad);
}
static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
@@ -6125,7 +6132,6 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
struct ipc_security_struct *isec;
struct common_audit_data ad;
u32 sid = current_sid();
- int rc;
isec = selinux_ipc(shp);
ipc_init_security(isec, SECCLASS_SHM);
@@ -6133,10 +6139,9 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = shp->key;
- rc = avc_has_perm(&selinux_state,
- sid, isec->sid, SECCLASS_SHM,
- SHM__CREATE, &ad);
- return rc;
+ return avc_has_perm(&selinux_state,
+ sid, isec->sid, SECCLASS_SHM,
+ SHM__CREATE, &ad);
}
static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
@@ -6210,7 +6215,6 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
struct ipc_security_struct *isec;
struct common_audit_data ad;
u32 sid = current_sid();
- int rc;
isec = selinux_ipc(sma);
ipc_init_security(isec, SECCLASS_SEM);
@@ -6218,10 +6222,9 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = sma->key;
- rc = avc_has_perm(&selinux_state,
- sid, isec->sid, SECCLASS_SEM,
- SEM__CREATE, &ad);
- return rc;
+ return avc_has_perm(&selinux_state,
+ sid, isec->sid, SECCLASS_SEM,
+ SEM__CREATE, &ad);
}
static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
@@ -6987,6 +6990,28 @@ static int selinux_uring_sqpoll(void)
return avc_has_perm(&selinux_state, sid, sid,
SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
}
+
+/**
+ * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed
+ * @ioucmd: the io_uring command structure
+ *
+ * Check to see if the current domain is allowed to execute an
+ * IORING_OP_URING_CMD against the device/file specified in @ioucmd.
+ *
+ */
+static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+ struct file *file = ioucmd->file;
+ struct inode *inode = file_inode(file);
+ struct inode_security_struct *isec = selinux_inode(inode);
+ struct common_audit_data ad;
+
+ ad.type = LSM_AUDIT_DATA_FILE;
+ ad.u.file = file;
+
+ return avc_has_perm(&selinux_state, current_sid(), isec->sid,
+ SECCLASS_IO_URING, IO_URING__CMD, &ad);
+}
#endif /* CONFIG_IO_URING */
/*
@@ -7111,6 +7136,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
LSM_HOOK_INIT(task_kill, selinux_task_kill),
LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
+ LSM_HOOK_INIT(userns_create, selinux_userns_create),
LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
@@ -7231,6 +7257,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
#ifdef CONFIG_IO_URING
LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds),
LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll),
+ LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd),
#endif
/*
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index ff757ae5f253..a3c380775d41 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -253,7 +253,9 @@ const struct security_class_mapping secclass_map[] = {
{ "anon_inode",
{ COMMON_FILE_PERMS, NULL } },
{ "io_uring",
- { "override_creds", "sqpoll", NULL } },
+ { "override_creds", "sqpoll", "cmd", NULL } },
+ { "user_namespace",
+ { "create", NULL } },
{ NULL }
};
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 8fcdd494af27..a00d19139436 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -71,7 +71,7 @@ struct selinux_fs_info {
struct dentry *bool_dir;
unsigned int bool_num;
char **bool_pending_names;
- unsigned int *bool_pending_values;
+ int *bool_pending_values;
struct dentry *class_dir;
unsigned long last_class_ino;
bool policy_opened;
@@ -356,7 +356,7 @@ static const struct file_operations sel_policyvers_ops = {
/* declaration for sel_write_load */
static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_dir,
unsigned int *bool_num, char ***bool_pending_names,
- unsigned int **bool_pending_values);
+ int **bool_pending_values);
static int sel_make_classes(struct selinux_policy *newpolicy,
struct dentry *class_dir,
unsigned long *last_class_ino);
@@ -527,7 +527,7 @@ static const struct file_operations sel_policy_ops = {
};
static void sel_remove_old_bool_data(unsigned int bool_num, char **bool_names,
- unsigned int *bool_values)
+ int *bool_values)
{
u32 i;
@@ -545,7 +545,7 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
struct dentry *tmp_parent, *tmp_bool_dir, *tmp_class_dir, *old_dentry;
unsigned int tmp_bool_num, old_bool_num;
char **tmp_bool_names, **old_bool_names;
- unsigned int *tmp_bool_values, *old_bool_values;
+ int *tmp_bool_values, *old_bool_values;
unsigned long tmp_ino = fsi->last_ino; /* Don't increment last_ino in this function */
tmp_parent = sel_make_disconnected_dir(fsi->sb, &tmp_ino);
@@ -1423,7 +1423,7 @@ static void sel_remove_entries(struct dentry *de)
static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_dir,
unsigned int *bool_num, char ***bool_pending_names,
- unsigned int **bool_pending_values)
+ int **bool_pending_values)
{
int ret;
ssize_t len;
@@ -1917,7 +1917,6 @@ static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
struct selinux_fs_info *fsi = sb->s_fs_info;
struct dentry *dentry = NULL;
struct inode *inode = NULL;
- int rc;
dentry = d_alloc_name(dir, "index");
if (!dentry)
@@ -1937,9 +1936,7 @@ static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
if (IS_ERR(dentry))
return PTR_ERR(dentry);
- rc = sel_make_perm_files(newpolicy, classname, index, dentry);
-
- return rc;
+ return sel_make_perm_files(newpolicy, classname, index, dentry);
}
static int sel_make_classes(struct selinux_policy *newpolicy,
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index 62990aa1ec9e..eda32c3d4c0a 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -38,7 +38,7 @@ static inline void mls_context_init(struct context *c)
memset(&c->range, 0, sizeof(c->range));
}
-static inline int mls_context_cpy(struct context *dst, struct context *src)
+static inline int mls_context_cpy(struct context *dst, const struct context *src)
{
int rc;
@@ -58,7 +58,7 @@ out:
/*
* Sets both levels in the MLS range of 'dst' to the low level of 'src'.
*/
-static inline int mls_context_cpy_low(struct context *dst, struct context *src)
+static inline int mls_context_cpy_low(struct context *dst, const struct context *src)
{
int rc;
@@ -78,7 +78,7 @@ out:
/*
* Sets both levels in the MLS range of 'dst' to the high level of 'src'.
*/
-static inline int mls_context_cpy_high(struct context *dst, struct context *src)
+static inline int mls_context_cpy_high(struct context *dst, const struct context *src)
{
int rc;
@@ -97,9 +97,10 @@ out:
static inline int mls_context_glblub(struct context *dst,
- struct context *c1, struct context *c2)
+ const struct context *c1, const struct context *c2)
{
- struct mls_range *dr = &dst->range, *r1 = &c1->range, *r2 = &c2->range;
+ struct mls_range *dr = &dst->range;
+ const struct mls_range *r1 = &c1->range, *r2 = &c2->range;
int rc = 0;
if (r1->level[1].sens < r2->level[0].sens ||
@@ -127,7 +128,7 @@ out:
return rc;
}
-static inline int mls_context_cmp(struct context *c1, struct context *c2)
+static inline int mls_context_cmp(const struct context *c1, const struct context *c2)
{
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
@@ -147,7 +148,7 @@ static inline void context_init(struct context *c)
memset(c, 0, sizeof(*c));
}
-static inline int context_cpy(struct context *dst, struct context *src)
+static inline int context_cpy(struct context *dst, const struct context *src)
{
int rc;
@@ -180,7 +181,7 @@ static inline void context_destroy(struct context *c)
mls_context_destroy(c);
}
-static inline int context_cmp(struct context *c1, struct context *c2)
+static inline int context_cmp(const struct context *c1, const struct context *c2)
{
if (c1->len && c2->len)
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index abde349c8321..d31b87be9a1e 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -28,9 +28,9 @@
static struct kmem_cache *ebitmap_node_cachep __ro_after_init;
-int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
+int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2)
{
- struct ebitmap_node *n1, *n2;
+ const struct ebitmap_node *n1, *n2;
if (e1->highbit != e2->highbit)
return 0;
@@ -50,9 +50,10 @@ int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
return 1;
}
-int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
+int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src)
{
- struct ebitmap_node *n, *new, *prev;
+ struct ebitmap_node *new, *prev;
+ const struct ebitmap_node *n;
ebitmap_init(dst);
n = src->node;
@@ -78,7 +79,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
return 0;
}
-int ebitmap_and(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2)
+int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2)
{
struct ebitmap_node *n;
int bit, rc;
@@ -217,9 +218,9 @@ netlbl_import_failure:
* if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
* last_e2bit.
*/
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
+int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit)
{
- struct ebitmap_node *n1, *n2;
+ const struct ebitmap_node *n1, *n2;
int i;
if (e1->highbit < e2->highbit)
@@ -258,9 +259,9 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
return 1;
}
-int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
+int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit)
{
- struct ebitmap_node *n;
+ const struct ebitmap_node *n;
if (e->highbit < bit)
return 0;
@@ -467,7 +468,7 @@ bad:
goto out;
}
-int ebitmap_write(struct ebitmap *e, void *fp)
+int ebitmap_write(const struct ebitmap *e, void *fp)
{
struct ebitmap_node *n;
u32 count;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 58eb822f11ee..e5b57dc3fc53 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -44,7 +44,7 @@ struct ebitmap {
#define ebitmap_length(e) ((e)->highbit)
-static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
+static inline unsigned int ebitmap_start_positive(const struct ebitmap *e,
struct ebitmap_node **n)
{
unsigned int ofs;
@@ -62,7 +62,7 @@ static inline void ebitmap_init(struct ebitmap *e)
memset(e, 0, sizeof(*e));
}
-static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
+static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
struct ebitmap_node **n,
unsigned int bit)
{
@@ -85,7 +85,7 @@ static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
#define EBITMAP_NODE_OFFSET(node, bit) \
(((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
-static inline int ebitmap_node_get_bit(struct ebitmap_node *n,
+static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
unsigned int bit)
{
unsigned int index = EBITMAP_NODE_INDEX(n, bit);
@@ -122,15 +122,15 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
(bit) < ebitmap_length(e); \
(bit) = ebitmap_next_positive(e, &(n), bit)) \
-int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
-int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
-int ebitmap_and(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2);
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit);
-int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
+int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2);
+int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src);
+int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2);
+int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit);
+int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e);
int ebitmap_read(struct ebitmap *e, void *fp);
-int ebitmap_write(struct ebitmap *e, void *fp);
+int ebitmap_write(const struct ebitmap *e, void *fp);
u32 ebitmap_hash(const struct ebitmap *e, u32 hash);
#ifdef CONFIG_NETLABEL
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index 068e0d7809db..7d48d5e52233 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -27,13 +27,13 @@ struct mls_range {
struct mls_level level[2]; /* low == level[0], high == level[1] */
};
-static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
+static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2)
{
return ((l1->sens == l2->sens) &&
ebitmap_cmp(&l1->cat, &l2->cat));
}
-static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2)
{
return ((l1->sens >= l2->sens) &&
ebitmap_contains(&l1->cat, &l2->cat, 0));
diff --git a/security/smack/smack.h b/security/smack/smack.h
index fc837dcebf96..e2239be7bd60 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -180,15 +180,6 @@ struct smack_known_list_elem {
struct smack_known *smk_label;
};
-/* Super block security struct flags for mount options */
-#define FSDEFAULT_MNT 0x01
-#define FSFLOOR_MNT 0x02
-#define FSHAT_MNT 0x04
-#define FSROOT_MNT 0x08
-#define FSTRANS_MNT 0x10
-
-#define NUM_SMK_MNT_OPTS 5
-
enum {
Opt_error = -1,
Opt_fsdefault = 0,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 434b348d8fcd..b6306d71c908 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -42,6 +42,7 @@
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/watch_queue.h>
+#include <linux/io_uring.h>
#include "smack.h"
#define TRANS_TRUE "TRUE"
@@ -496,13 +497,11 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
*/
static int smack_ptrace_traceme(struct task_struct *ptp)
{
- int rc;
struct smack_known *skp;
skp = smk_of_task(smack_cred(current_cred()));
- rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
- return rc;
+ return smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
}
/**
@@ -2279,6 +2278,21 @@ static void smack_sk_free_security(struct sock *sk)
}
/**
+ * smack_sk_clone_security - Copy security context
+ * @sk: the old socket
+ * @newsk: the new socket
+ *
+ * Copy the security context of the old socket pointer to the cloned
+ */
+static void smack_sk_clone_security(const struct sock *sk, struct sock *newsk)
+{
+ struct socket_smack *ssp_old = sk->sk_security;
+ struct socket_smack *ssp_new = newsk->sk_security;
+
+ *ssp_new = *ssp_old;
+}
+
+/**
* smack_ipv4host_label - check host based restrictions
* @sip: the object end
*
@@ -4732,6 +4746,36 @@ static int smack_uring_sqpoll(void)
return -EPERM;
}
+/**
+ * smack_uring_cmd - check on file operations for io_uring
+ * @ioucmd: the command in question
+ *
+ * Make a best guess about whether a io_uring "command" should
+ * be allowed. Use the same logic used for determining if the
+ * file could be opened for read in the absence of better criteria.
+ */
+static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+ struct file *file = ioucmd->file;
+ struct smk_audit_info ad;
+ struct task_smack *tsp;
+ struct inode *inode;
+ int rc;
+
+ if (!file)
+ return -EINVAL;
+
+ tsp = smack_cred(file->f_cred);
+ inode = file_inode(file);
+
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+ smk_ad_setfield_u_fs_path(&ad, file->f_path);
+ rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
+ rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
+
+ return rc;
+}
+
#endif /* CONFIG_IO_URING */
struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
@@ -4851,6 +4895,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+ LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security),
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
@@ -4889,6 +4934,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
#ifdef CONFIG_IO_URING
LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds),
LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll),
+ LSM_HOOK_INIT(uring_cmd, smack_uring_cmd),
#endif
};
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 023bedd9dfa3..7cf8fdbb29bf 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -423,7 +423,7 @@ void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...)
int len;
va_start(args, fmt);
- len = vsnprintf((char *) &len, 1, fmt, args) + 1;
+ len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
va_start(args, fmt);
tomoyo_write_log2(r, len, fmt, args);
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index ff17abc96e5c..f4cd9b58b205 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -2057,7 +2057,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
bool quota_exceeded = false;
va_start(args, fmt);
- len = vsnprintf((char *) &len, 1, fmt, args) + 1;
+ len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
/* Write /sys/kernel/security/tomoyo/audit. */
va_start(args, fmt);
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 1e6077568fde..8f3b90b6e03d 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -717,7 +717,7 @@ int tomoyo_path_number_perm(const u8 type, const struct path *path,
int idx;
if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
- == TOMOYO_CONFIG_DISABLED || !path->dentry)
+ == TOMOYO_CONFIG_DISABLED)
return 0;
idx = tomoyo_read_lock();
if (!tomoyo_get_realpath(&buf, path))
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index df4798980416..1c483ee7f93d 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -240,11 +240,8 @@ char *tomoyo_realpath_from_path(const struct path *path)
char *name = NULL;
unsigned int buf_len = PAGE_SIZE / 2;
struct dentry *dentry = path->dentry;
- struct super_block *sb;
+ struct super_block *sb = dentry->d_sb;
- if (!dentry)
- return NULL;
- sb = dentry->d_sb;
while (1) {
char *pos;
struct inode *inode;
@@ -264,10 +261,8 @@ char *tomoyo_realpath_from_path(const struct path *path)
inode = d_backing_inode(sb->s_root);
/*
* Get local name for filesystems without rename() operation
- * or dentry without vfsmount.
*/
- if (!path->mnt ||
- (!inode->i_op->rename &&
+ if ((!inode->i_op->rename &&
!(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
pos = tomoyo_get_local_path(path->dentry, buf,
buf_len - 1);