Skip to content

Commit 1086eea

Browse files
committed
Merge tag 'lsm-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
Pull LSM updates from Paul Moore: - Add proper multi-LSM support for xattrs in the security_inode_init_security() hook Historically the LSM layer has only allowed a single LSM to add an xattr to an inode, with IMA/EVM measuring that and adding its own as well. As we work towards promoting IMA/EVM to a "proper LSM" instead of the special case that it is now, we need to better support the case of multiple LSMs each adding xattrs to an inode and after several attempts we now appear to have something that is working well. It is worth noting that in the process of making this change we uncovered a problem with Smack's SMACK64TRANSMUTE xattr which is also fixed in this pull request. - Additional LSM hook constification Two patches to constify parameters to security_capget() and security_binder_transfer_file(). While I generally don't make a special note of who submitted these patches, these were the work of an Outreachy intern, Khadija Kamran, and that makes me happy; hopefully it does the same for all of you reading this. - LSM hook comment header fixes One patch to add a missing hook comment header, one to fix a minor typo. - Remove an old, unused credential function declaration It wasn't clear to me who should pick this up, but it was trivial, obviously correct, and arguably the LSM layer has a vested interest in credentials so I merged it. Sadly I'm now noticing that despite my subject line cleanup I didn't cleanup the "unsued" misspelling, sigh * tag 'lsm-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: lsm: constify the 'file' parameter in security_binder_transfer_file() lsm: constify the 'target' parameter in security_capget() lsm: add comment block for security_sk_classify_flow LSM hook security: Fix ret values doc for security_inode_init_security() cred: remove unsued extern declaration change_create_files_as() evm: Support multiple LSMs providing an xattr evm: Align evm_inode_init_security() definition with LSM infrastructure smack: Set the SMACK64TRANSMUTE xattr in smack_inode_init_security() security: Allow all LSMs to provide xattrs for inode_init_security hook lsm: fix typo in security_file_lock() comment header
2 parents 1dbae18 + 8e4672d commit 1086eea

15 files changed

Lines changed: 202 additions & 101 deletions

File tree

include/linux/cred.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ extern void abort_creds(struct cred *);
164164
extern const struct cred *override_creds(const struct cred *);
165165
extern void revert_creds(const struct cred *);
166166
extern struct cred *prepare_kernel_cred(struct task_struct *);
167-
extern int change_create_files_as(struct cred *, struct inode *);
168167
extern int set_security_override(struct cred *, u32);
169168
extern int set_security_override_from_ctx(struct cred *, const char *);
170169
extern int set_create_files_as(struct cred *, struct inode *);

include/linux/evm.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
5656
{
5757
return evm_inode_post_setxattr(dentry, acl_name, NULL, 0);
5858
}
59-
extern int evm_inode_init_security(struct inode *inode,
60-
const struct xattr *xattr_array,
61-
struct xattr *evm);
59+
60+
int evm_inode_init_security(struct inode *inode, struct inode *dir,
61+
const struct qstr *qstr, struct xattr *xattrs,
62+
int *xattr_count);
6263
extern bool evm_revalidate_status(const char *xattr_name);
6364
extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
6465
extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
@@ -157,9 +158,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
157158
return;
158159
}
159160

160-
static inline int evm_inode_init_security(struct inode *inode,
161-
const struct xattr *xattr_array,
162-
struct xattr *evm)
161+
static inline int evm_inode_init_security(struct inode *inode, struct inode *dir,
162+
const struct qstr *qstr,
163+
struct xattr *xattrs,
164+
int *xattr_count)
163165
{
164166
return 0;
165167
}

include/linux/lsm_hook_defs.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ LSM_HOOK(int, 0, binder_transaction, const struct cred *from,
3232
LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from,
3333
const struct cred *to)
3434
LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from,
35-
const struct cred *to, struct file *file)
35+
const struct cred *to, const struct file *file)
3636
LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child,
3737
unsigned int mode)
3838
LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent)
39-
LSM_HOOK(int, 0, capget, struct task_struct *target, kernel_cap_t *effective,
39+
LSM_HOOK(int, 0, capget, const struct task_struct *target, kernel_cap_t *effective,
4040
kernel_cap_t *inheritable, kernel_cap_t *permitted)
4141
LSM_HOOK(int, 0, capset, struct cred *new, const struct cred *old,
4242
const kernel_cap_t *effective, const kernel_cap_t *inheritable,
@@ -112,9 +112,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
112112
unsigned int obj_type)
113113
LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
114114
LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
115-
LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
116-
struct inode *dir, const struct qstr *qstr, const char **name,
117-
void **value, size_t *len)
115+
LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
116+
struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
117+
int *xattr_count)
118118
LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
119119
const struct qstr *name, const struct inode *context_inode)
120120
LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,

include/linux/lsm_hooks.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/security.h>
2929
#include <linux/init.h>
3030
#include <linux/rculist.h>
31+
#include <linux/xattr.h>
3132

3233
union security_list_options {
3334
#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
@@ -63,8 +64,27 @@ struct lsm_blob_sizes {
6364
int lbs_ipc;
6465
int lbs_msg_msg;
6566
int lbs_task;
67+
int lbs_xattr_count; /* number of xattr slots in new_xattrs array */
6668
};
6769

70+
/**
71+
* lsm_get_xattr_slot - Return the next available slot and increment the index
72+
* @xattrs: array storing LSM-provided xattrs
73+
* @xattr_count: number of already stored xattrs (updated)
74+
*
75+
* Retrieve the first available slot in the @xattrs array to fill with an xattr,
76+
* and increment @xattr_count.
77+
*
78+
* Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
79+
*/
80+
static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
81+
int *xattr_count)
82+
{
83+
if (unlikely(!xattrs))
84+
return NULL;
85+
return &xattrs[(*xattr_count)++];
86+
}
87+
6888
/*
6989
* LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
7090
* LSM hooks (in include/linux/lsm_hook_defs.h).

include/linux/security.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
145145
extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
146146
extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
147147
extern int cap_ptrace_traceme(struct task_struct *parent);
148-
extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
148+
extern int cap_capget(const struct task_struct *target, kernel_cap_t *effective,
149+
kernel_cap_t *inheritable, kernel_cap_t *permitted);
149150
extern int cap_capset(struct cred *new, const struct cred *old,
150151
const kernel_cap_t *effective,
151152
const kernel_cap_t *inheritable,
@@ -268,10 +269,10 @@ int security_binder_transaction(const struct cred *from,
268269
int security_binder_transfer_binder(const struct cred *from,
269270
const struct cred *to);
270271
int security_binder_transfer_file(const struct cred *from,
271-
const struct cred *to, struct file *file);
272+
const struct cred *to, const struct file *file);
272273
int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
273274
int security_ptrace_traceme(struct task_struct *parent);
274-
int security_capget(struct task_struct *target,
275+
int security_capget(const struct task_struct *target,
275276
kernel_cap_t *effective,
276277
kernel_cap_t *inheritable,
277278
kernel_cap_t *permitted);
@@ -538,7 +539,7 @@ static inline int security_binder_transfer_binder(const struct cred *from,
538539

539540
static inline int security_binder_transfer_file(const struct cred *from,
540541
const struct cred *to,
541-
struct file *file)
542+
const struct file *file)
542543
{
543544
return 0;
544545
}
@@ -554,7 +555,7 @@ static inline int security_ptrace_traceme(struct task_struct *parent)
554555
return cap_ptrace_traceme(parent);
555556
}
556557

557-
static inline int security_capget(struct task_struct *target,
558+
static inline int security_capget(const struct task_struct *target,
558559
kernel_cap_t *effective,
559560
kernel_cap_t *inheritable,
560561
kernel_cap_t *permitted)

kernel/capability.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
112112
int ret;
113113

114114
if (pid && (pid != task_pid_vnr(current))) {
115-
struct task_struct *target;
115+
const struct task_struct *target;
116116

117117
rcu_read_lock();
118118

security/apparmor/lsm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static int apparmor_ptrace_traceme(struct task_struct *parent)
144144
}
145145

146146
/* Derived from security/commoncap.c:cap_capget */
147-
static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
147+
static int apparmor_capget(const struct task_struct *target, kernel_cap_t *effective,
148148
kernel_cap_t *inheritable, kernel_cap_t *permitted)
149149
{
150150
struct aa_label *label;

security/commoncap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ int cap_ptrace_traceme(struct task_struct *parent)
197197
* This function retrieves the capabilities of the nominated task and returns
198198
* them to the caller.
199199
*/
200-
int cap_capget(struct task_struct *target, kernel_cap_t *effective,
200+
int cap_capget(const struct task_struct *target, kernel_cap_t *effective,
201201
kernel_cap_t *inheritable, kernel_cap_t *permitted)
202202
{
203203
const struct cred *cred;

security/integrity/evm/evm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ struct evm_digest {
4646
char digest[IMA_MAX_DIGEST_SIZE];
4747
} __packed;
4848

49+
int evm_protected_xattr(const char *req_xattr_name);
50+
4951
int evm_init_key(void);
5052
int evm_update_evmxattr(struct dentry *dentry,
5153
const char *req_xattr_name,
@@ -58,7 +60,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
5860
const char *req_xattr_value,
5961
size_t req_xattr_value_len, char type,
6062
struct evm_digest *data);
61-
int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
63+
int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
6264
char *hmac_val);
6365
int evm_init_secfs(void);
6466

security/integrity/evm/evm_crypto.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,18 +385,25 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
385385
return rc;
386386
}
387387

388-
int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
388+
int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
389389
char *hmac_val)
390390
{
391391
struct shash_desc *desc;
392+
const struct xattr *xattr;
392393

393394
desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
394395
if (IS_ERR(desc)) {
395396
pr_info("init_desc failed\n");
396397
return PTR_ERR(desc);
397398
}
398399

399-
crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
400+
for (xattr = xattrs; xattr->name; xattr++) {
401+
if (!evm_protected_xattr(xattr->name))
402+
continue;
403+
404+
crypto_shash_update(desc, xattr->value, xattr->value_len);
405+
}
406+
400407
hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
401408
kfree(desc);
402409
return 0;

0 commit comments

Comments
 (0)