diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/lsm.c | 2 | ||||
-rw-r--r-- | security/integrity/digsig_asymmetric.c | 3 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 | ||||
-rw-r--r-- | security/keys/trusted-keys/trusted_core.c | 1 | ||||
-rw-r--r-- | security/landlock/limits.h | 2 | ||||
-rw-r--r-- | security/landlock/ruleset.c | 4 | ||||
-rw-r--r-- | security/landlock/ruleset.h | 24 | ||||
-rw-r--r-- | security/landlock/syscalls.c | 17 | ||||
-rw-r--r-- | security/min_addr.c | 2 | ||||
-rw-r--r-- | security/security.c | 70 | ||||
-rw-r--r-- | security/selinux/hooks.c | 38 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.h | 2 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 48 | ||||
-rw-r--r-- | security/yama/yama_lsm.c | 2 |
15 files changed, 136 insertions, 82 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 6239777090c4..16568b6d589d 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -2029,7 +2029,7 @@ static int __init alloc_buffers(void) } #ifdef CONFIG_SYSCTL -static int apparmor_dointvec(struct ctl_table *table, int write, +static int apparmor_dointvec(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { if (!aa_current_policy_admin_capable(NULL)) diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index de603cf42ac7..457c0a396caf 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -114,8 +114,7 @@ int asymmetric_verify(struct key *keyring, const char *sig, } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) { /* edcsa-nist-p192 etc. */ pks.encoding = "x962"; - } else if (!strcmp(pk->pkey_algo, "ecrdsa") || - !strcmp(pk->pkey_algo, "sm2")) { + } else if (!strcmp(pk->pkey_algo, "ecrdsa")) { pks.encoding = "raw"; } else { ret = -ENOPKG; diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 8af2136069d2..831cb84fd75a 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -1040,4 +1040,5 @@ static void __exit cleanup_encrypted(void) late_initcall(init_encrypted); module_exit(cleanup_encrypted); +MODULE_DESCRIPTION("Encrypted key type"); MODULE_LICENSE("GPL"); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4bc3e9398ee3..ab927a142f51 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1694,7 +1694,7 @@ long keyctl_session_to_parent(void) goto unlock; /* cancel an already pending keyring replacement */ - oldwork = task_work_cancel(parent, key_change_session_keyring); + oldwork = task_work_cancel_func(parent, key_change_session_keyring); /* the replacement session keyring is applied just prior to userspace * restarting */ diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index 5113aeae5628..e2d9644efde1 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -395,4 +395,5 @@ static void __exit cleanup_trusted(void) late_initcall(init_trusted); module_exit(cleanup_trusted); +MODULE_DESCRIPTION("Trusted Key type"); MODULE_LICENSE("GPL"); diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 20fdb5ff3514..4eb643077a2a 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -21,12 +21,10 @@ #define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL_DEV #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) -#define LANDLOCK_SHIFT_ACCESS_FS 0 #define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP #define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1) #define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET) -#define LANDLOCK_SHIFT_ACCESS_NET LANDLOCK_NUM_ACCESS_FS /* clang-format on */ diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index e0a5fbf9201a..6ff232f58618 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -169,13 +169,9 @@ static void build_check_ruleset(void) .num_rules = ~0, .num_layers = ~0, }; - typeof(ruleset.access_masks[0]) access_masks = ~0; BUILD_BUG_ON(ruleset.num_rules < LANDLOCK_MAX_NUM_RULES); BUILD_BUG_ON(ruleset.num_layers < LANDLOCK_MAX_NUM_LAYERS); - BUILD_BUG_ON(access_masks < - ((LANDLOCK_MASK_ACCESS_FS << LANDLOCK_SHIFT_ACCESS_FS) | - (LANDLOCK_MASK_ACCESS_NET << LANDLOCK_SHIFT_ACCESS_NET))); } /** diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h index c7f1526784fd..0f1b5b4c8f6b 100644 --- a/security/landlock/ruleset.h +++ b/security/landlock/ruleset.h @@ -39,10 +39,10 @@ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_NET); static_assert(sizeof(unsigned long) >= sizeof(access_mask_t)); /* Ruleset access masks. */ -typedef u32 access_masks_t; -/* Makes sure all ruleset access rights can be stored. */ -static_assert(BITS_PER_TYPE(access_masks_t) >= - LANDLOCK_NUM_ACCESS_FS + LANDLOCK_NUM_ACCESS_NET); +struct access_masks { + access_mask_t fs : LANDLOCK_NUM_ACCESS_FS; + access_mask_t net : LANDLOCK_NUM_ACCESS_NET; +}; typedef u16 layer_mask_t; /* Makes sure all layers can be checked. */ @@ -226,7 +226,7 @@ struct landlock_ruleset { * layers are set once and never changed for the * lifetime of the ruleset. */ - access_masks_t access_masks[]; + struct access_masks access_masks[]; }; }; }; @@ -265,8 +265,7 @@ landlock_add_fs_access_mask(struct landlock_ruleset *const ruleset, /* Should already be checked in sys_landlock_create_ruleset(). */ WARN_ON_ONCE(fs_access_mask != fs_mask); - ruleset->access_masks[layer_level] |= - (fs_mask << LANDLOCK_SHIFT_ACCESS_FS); + ruleset->access_masks[layer_level].fs |= fs_mask; } static inline void @@ -278,17 +277,14 @@ landlock_add_net_access_mask(struct landlock_ruleset *const ruleset, /* Should already be checked in sys_landlock_create_ruleset(). */ WARN_ON_ONCE(net_access_mask != net_mask); - ruleset->access_masks[layer_level] |= - (net_mask << LANDLOCK_SHIFT_ACCESS_NET); + ruleset->access_masks[layer_level].net |= net_mask; } static inline access_mask_t landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset, const u16 layer_level) { - return (ruleset->access_masks[layer_level] >> - LANDLOCK_SHIFT_ACCESS_FS) & - LANDLOCK_MASK_ACCESS_FS; + return ruleset->access_masks[layer_level].fs; } static inline access_mask_t @@ -304,9 +300,7 @@ static inline access_mask_t landlock_get_net_access_mask(const struct landlock_ruleset *const ruleset, const u16 layer_level) { - return (ruleset->access_masks[layer_level] >> - LANDLOCK_SHIFT_ACCESS_NET) & - LANDLOCK_MASK_ACCESS_NET; + return ruleset->access_masks[layer_level].net; } bool landlock_unmask_layers(const struct landlock_rule *const rule, diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 03b470f5a85a..ccc8bc6c1584 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -378,8 +378,7 @@ static int add_rule_net_port(struct landlock_ruleset *ruleset, * with the new rule. * @rule_type: Identify the structure type pointed to by @rule_attr: * %LANDLOCK_RULE_PATH_BENEATH or %LANDLOCK_RULE_NET_PORT. - * @rule_attr: Pointer to a rule (only of type &struct - * landlock_path_beneath_attr for now). + * @rule_attr: Pointer to a rule (matching the @rule_type). * @flags: Must be 0. * * This system call enables to define a new rule and add it to an existing @@ -390,18 +389,20 @@ static int add_rule_net_port(struct landlock_ruleset *ruleset, * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time; * - %EAFNOSUPPORT: @rule_type is %LANDLOCK_RULE_NET_PORT but TCP/IP is not * supported by the running kernel; - * - %EINVAL: @flags is not 0, or inconsistent access in the rule (i.e. + * - %EINVAL: @flags is not 0; + * - %EINVAL: The rule accesses are inconsistent (i.e. * &landlock_path_beneath_attr.allowed_access or - * &landlock_net_port_attr.allowed_access is not a subset of the - * ruleset handled accesses), or &landlock_net_port_attr.port is - * greater than 65535; - * - %ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access); + * &landlock_net_port_attr.allowed_access is not a subset of the ruleset + * handled accesses) + * - %EINVAL: &landlock_net_port_attr.port is greater than 65535; + * - %ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access is + * 0); * - %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 * @rule_attr is not the expected file descriptor type; * - %EPERM: @ruleset_fd has no write access to the underlying ruleset; - * - %EFAULT: @rule_attr inconsistency. + * - %EFAULT: @rule_attr was not a valid address. */ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd, const enum landlock_rule_type, rule_type, diff --git a/security/min_addr.c b/security/min_addr.c index 88c9a6a21f47..0ce267c041ab 100644 --- a/security/min_addr.c +++ b/security/min_addr.c @@ -29,7 +29,7 @@ static void update_mmap_min_addr(void) * sysctl handler which just sets dac_mmap_min_addr = the new value and then * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly */ -int mmap_min_addr_handler(struct ctl_table *table, int write, +int mmap_min_addr_handler(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { int ret; diff --git a/security/security.c b/security/security.c index e5ca08789f74..8cee5b6c6e6d 100644 --- a/security/security.c +++ b/security/security.c @@ -2278,7 +2278,20 @@ int security_inode_getattr(const struct path *path) * @size: size of xattr value * @flags: flags * - * Check permission before setting the extended attributes. + * This hook performs the desired permission checks before setting the extended + * attributes (xattrs) on @dentry. It is important to note that we have some + * additional logic before the main LSM implementation calls to detect if we + * need to perform an additional capability check at the LSM layer. + * + * Normally we enforce a capability check prior to executing the various LSM + * hook implementations, but if a LSM wants to avoid this capability check, + * it can register a 'inode_xattr_skipcap' hook and return a value of 1 for + * xattrs that it wants to avoid the capability check, leaving the LSM fully + * responsible for enforcing the access control for the specific xattr. If all + * of the enabled LSMs refrain from registering a 'inode_xattr_skipcap' hook, + * or return a 0 (the default return value), the capability check is still + * performed. If no 'inode_xattr_skipcap' hooks are registered the capability + * check is performed. * * Return: Returns 0 if permission is granted. */ @@ -2286,20 +2299,20 @@ int security_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - int ret; + int rc; if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - /* - * SELinux and Smack integrate the cap call, - * so assume that all LSMs supplying this call do so. - */ - ret = call_int_hook(inode_setxattr, idmap, dentry, name, value, size, - flags); - if (ret == 1) - ret = cap_inode_setxattr(dentry, name, value, size, flags); - return ret; + /* enforce the capability checks at the lsm layer, if needed */ + if (!call_int_hook(inode_xattr_skipcap, name)) { + rc = cap_inode_setxattr(dentry, name, value, size, flags); + if (rc) + return rc; + } + + return call_int_hook(inode_setxattr, idmap, dentry, name, value, size, + flags); } /** @@ -2452,26 +2465,39 @@ int security_inode_listxattr(struct dentry *dentry) * @dentry: file * @name: xattr name * - * Check permission before removing the extended attribute identified by @name - * for @dentry. + * This hook performs the desired permission checks before setting the extended + * attributes (xattrs) on @dentry. It is important to note that we have some + * additional logic before the main LSM implementation calls to detect if we + * need to perform an additional capability check at the LSM layer. + * + * Normally we enforce a capability check prior to executing the various LSM + * hook implementations, but if a LSM wants to avoid this capability check, + * it can register a 'inode_xattr_skipcap' hook and return a value of 1 for + * xattrs that it wants to avoid the capability check, leaving the LSM fully + * responsible for enforcing the access control for the specific xattr. If all + * of the enabled LSMs refrain from registering a 'inode_xattr_skipcap' hook, + * or return a 0 (the default return value), the capability check is still + * performed. If no 'inode_xattr_skipcap' hooks are registered the capability + * check is performed. * * Return: Returns 0 if permission is granted. */ int security_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name) { - int ret; + int rc; if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - /* - * SELinux and Smack integrate the cap call, - * so assume that all LSMs supplying this call do so. - */ - ret = call_int_hook(inode_removexattr, idmap, dentry, name); - if (ret == 1) - ret = cap_inode_removexattr(idmap, dentry, name); - return ret; + + /* enforce the capability checks at the lsm layer, if needed */ + if (!call_int_hook(inode_xattr_skipcap, name)) { + rc = cap_inode_removexattr(idmap, dentry, name); + if (rc) + return rc; + } + + return call_int_hook(inode_removexattr, idmap, dentry, name); } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7eed331e90f0..55c78c318ccd 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3177,6 +3177,23 @@ static bool has_cap_mac_admin(bool audit) return true; } +/** + * selinux_inode_xattr_skipcap - Skip the xattr capability checks? + * @name: name of the xattr + * + * Returns 1 to indicate that SELinux "owns" the access control rights to xattrs + * named @name; the LSM layer should avoid enforcing any traditional + * capability based access controls on this xattr. Returns 0 to indicate that + * SELinux does not "own" the access control rights to xattrs named @name and is + * deferring to the LSM layer for further access controls, including capability + * based controls. + */ +static int selinux_inode_xattr_skipcap(const char *name) +{ + /* require capability check if not a selinux xattr */ + return !strcmp(name, XATTR_NAME_SELINUX); +} + static int selinux_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) @@ -3188,15 +3205,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, u32 newsid, sid = current_sid(); int rc = 0; - if (strcmp(name, XATTR_NAME_SELINUX)) { - rc = cap_inode_setxattr(dentry, name, value, size, flags); - if (rc) - return rc; - - /* Not an attribute we recognize, so just check the - ordinary setattr permission. */ + /* if not a selinux xattr, only check the ordinary setattr perm */ + if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - } if (!selinux_initialized()) return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM); @@ -3345,15 +3356,9 @@ static int selinux_inode_listxattr(struct dentry *dentry) static int selinux_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name) { - if (strcmp(name, XATTR_NAME_SELINUX)) { - int rc = cap_inode_removexattr(idmap, dentry, name); - if (rc) - return rc; - - /* Not an attribute we recognize, so just check the - ordinary setattr permission. */ + /* if not a selinux xattr, only check the ordinary setattr perm */ + if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - } if (!selinux_initialized()) return 0; @@ -7175,6 +7180,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_permission, selinux_inode_permission), LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr), LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr), + LSM_HOOK_INIT(inode_xattr_skipcap, selinux_inode_xattr_skipcap), LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr), LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr), LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr), diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index 24d7d8b3cda3..ba2ac3da1153 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -29,7 +29,7 @@ sizeof(unsigned long)) #define EBITMAP_UNIT_SIZE BITS_PER_LONG #define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) -#define EBITMAP_BIT 1ULL +#define EBITMAP_BIT 1UL #define EBITMAP_SHIFT_UNIT_SIZE(x) \ (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f5cbec1e6a92..4164699cd4f6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1283,6 +1283,33 @@ static int smack_inode_getattr(const struct path *path) } /** + * smack_inode_xattr_skipcap - Skip the xattr capability checks? + * @name: name of the xattr + * + * Returns 1 to indicate that Smack "owns" the access control rights to xattrs + * named @name; the LSM layer should avoid enforcing any traditional + * capability based access controls on this xattr. Returns 0 to indicate that + * Smack does not "own" the access control rights to xattrs named @name and is + * deferring to the LSM layer for further access controls, including capability + * based controls. + */ +static int smack_inode_xattr_skipcap(const char *name) +{ + if (strncmp(name, XATTR_SMACK_SUFFIX, strlen(XATTR_SMACK_SUFFIX))) + return 0; + + if (strcmp(name, XATTR_NAME_SMACK) == 0 || + strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || + strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || + strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || + strcmp(name, XATTR_NAME_SMACKMMAP) == 0 || + strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) + return 1; + + return 0; +} + +/** * smack_inode_setxattr - Smack check for setting xattrs * @idmap: idmap of the mount * @dentry: the object @@ -1325,8 +1352,7 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap, size != TRANS_TRUE_SIZE || strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) rc = -EINVAL; - } else - rc = cap_inode_setxattr(dentry, name, value, size, flags); + } if (check_priv && !smack_privileged(CAP_MAC_ADMIN)) rc = -EPERM; @@ -1435,8 +1461,7 @@ static int smack_inode_removexattr(struct mnt_idmap *idmap, strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { if (!smack_privileged(CAP_MAC_ADMIN)) rc = -EPERM; - } else - rc = cap_inode_removexattr(idmap, dentry, name); + } if (rc != 0) return rc; @@ -3846,12 +3871,18 @@ static int smack_unix_stream_connect(struct sock *sock, } } - /* - * Cross reference the peer labels for SO_PEERSEC. - */ if (rc == 0) { + /* + * Cross reference the peer labels for SO_PEERSEC. + */ nsp->smk_packet = ssp->smk_out; ssp->smk_packet = osp->smk_out; + + /* + * new/child/established socket must inherit listening socket labels + */ + nsp->smk_out = osp->smk_out; + nsp->smk_in = osp->smk_in; } return rc; @@ -4431,7 +4462,7 @@ static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb, rcu_read_unlock(); if (hskp == NULL) - rc = netlbl_req_setattr(req, &skp->smk_netlabel); + rc = netlbl_req_setattr(req, &ssp->smk_out->smk_netlabel); else netlbl_req_delattr(req); @@ -5053,6 +5084,7 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_permission, smack_inode_permission), LSM_HOOK_INIT(inode_setattr, smack_inode_setattr), LSM_HOOK_INIT(inode_getattr, smack_inode_getattr), + LSM_HOOK_INIT(inode_xattr_skipcap, smack_inode_xattr_skipcap), LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr), LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr), LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr), diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 39944a859ff6..e1a5e13ea269 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -436,7 +436,7 @@ static struct security_hook_list yama_hooks[] __ro_after_init = { }; #ifdef CONFIG_SYSCTL -static int yama_dointvec_minmax(struct ctl_table *table, int write, +static int yama_dointvec_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { struct ctl_table table_copy; |