Skip to content

Commit f8cf2f1

Browse files
committed
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull integrity updates from James Morris: "A mixture of bug fixes, code cleanup, and continues to close IMA-measurement, IMA-appraisal, and IMA-audit gaps. Also note the addition of a new cred_getsecid LSM hook by Matthew Garrett: For IMA purposes, we want to be able to obtain the prepared secid in the bprm structure before the credentials are committed. Add a cred_getsecid hook that makes this possible. which is used by a new CREDS_CHECK target in IMA: In ima_bprm_check(), check with both the existing process credentials and the credentials that will be committed when the new process is started. This will not change behaviour unless the system policy is extended to include CREDS_CHECK targets - BPRM_CHECK will continue to check the same credentials that it did previously" * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: ima: Fallback to the builtin hash algorithm ima: Add smackfs to the default appraise/measure list evm: check for remount ro in progress before writing ima: Improvements in ima_appraise_measurement() ima: Simplify ima_eventsig_init() integrity: Remove unused macro IMA_ACTION_RULE_FLAGS ima: drop vla in ima_audit_measurement() ima: Fix Kconfig to select TPM 2.0 CRB interface evm: Constify *integrity_status_msg[] evm: Move evm_hmac and evm_hash from evm_main.c to evm_crypto.c fuse: define the filesystem as untrusted ima: fail signature verification based on policy ima: clear IMA_HASH ima: re-evaluate files on privileged mounted filesystems ima: fail file signature verification on non-init mounted filesystems IMA: Support using new creds in appraisal policy security: Add a cred_getsecid hook
2 parents 4b3f1a1 + ab60368 commit f8cf2f1

File tree

22 files changed

+227
-70
lines changed

22 files changed

+227
-70
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Description:
2626
[obj_user=] [obj_role=] [obj_type=]]
2727
option: [[appraise_type=]] [permit_directio]
2828

29-
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
29+
base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
3030
[FIRMWARE_CHECK]
3131
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
3232
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,8 @@
15211521

15221522
ima_policy= [IMA]
15231523
The builtin policies to load during IMA setup.
1524-
Format: "tcb | appraise_tcb | secure_boot"
1524+
Format: "tcb | appraise_tcb | secure_boot |
1525+
fail_securely"
15251526

15261527
The "tcb" policy measures all programs exec'd, files
15271528
mmap'd for exec, and all files opened with the read
@@ -1536,6 +1537,11 @@
15361537
of files (eg. kexec kernel image, kernel modules,
15371538
firmware, policy, etc) based on file signatures.
15381539

1540+
The "fail_securely" policy forces file signature
1541+
verification failure also on privileged mounted
1542+
filesystems with the SB_I_UNVERIFIABLE_SIGNATURE
1543+
flag.
1544+
15391545
ima_tcb [IMA] Deprecated. Use ima_policy= instead.
15401546
Load a policy which meets the needs of the Trusted
15411547
Computing Base. This means IMA will measure all

fs/fuse/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,9 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
10801080
sb->s_maxbytes = MAX_LFS_FILESIZE;
10811081
sb->s_time_gran = 1;
10821082
sb->s_export_op = &fuse_export_operations;
1083+
sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
1084+
if (sb->s_user_ns != &init_user_ns)
1085+
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
10831086

10841087
file = fget(d.fd);
10851088
err = -EINVAL;

include/linux/fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,8 @@ extern int send_sigurg(struct fown_struct *fown);
13211321

13221322
/* sb->s_iflags to limit user namespace mounts */
13231323
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
1324+
#define SB_I_IMA_UNVERIFIABLE_SIGNATURE 0x00000020
1325+
#define SB_I_UNTRUSTED_MOUNTER 0x00000040
13241326

13251327
/* Possible states of 'frozen' field */
13261328
enum {

include/linux/lsm_hooks.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@
554554
* @new points to the new credentials.
555555
* @old points to the original credentials.
556556
* Transfer data from original creds to new creds
557+
* @cred_getsecid:
558+
* Retrieve the security identifier of the cred structure @c
559+
* @c contains the credentials, secid will be placed into @secid.
560+
* In case of failure, @secid will be set to zero.
557561
* @kernel_act_as:
558562
* Set the credentials for a kernel service to act as (subjective context).
559563
* @new points to the credentials to be modified.
@@ -1569,6 +1573,7 @@ union security_list_options {
15691573
int (*cred_prepare)(struct cred *new, const struct cred *old,
15701574
gfp_t gfp);
15711575
void (*cred_transfer)(struct cred *new, const struct cred *old);
1576+
void (*cred_getsecid)(const struct cred *c, u32 *secid);
15721577
int (*kernel_act_as)(struct cred *new, u32 secid);
15731578
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
15741579
int (*kernel_module_request)(char *kmod_name);
@@ -1858,6 +1863,7 @@ struct security_hook_heads {
18581863
struct hlist_head cred_free;
18591864
struct hlist_head cred_prepare;
18601865
struct hlist_head cred_transfer;
1866+
struct hlist_head cred_getsecid;
18611867
struct hlist_head kernel_act_as;
18621868
struct hlist_head kernel_create_files_as;
18631869
struct hlist_head kernel_read_file;

include/linux/security.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
322322
void security_cred_free(struct cred *cred);
323323
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
324324
void security_transfer_creds(struct cred *new, const struct cred *old);
325+
void security_cred_getsecid(const struct cred *c, u32 *secid);
325326
int security_kernel_act_as(struct cred *new, u32 secid);
326327
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
327328
int security_kernel_module_request(char *kmod_name);

security/integrity/evm/evm.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
EVM_ALLOW_METADATA_WRITES)
3232

3333
extern int evm_initialized;
34-
extern char *evm_hmac;
35-
extern char *evm_hash;
3634

3735
#define EVM_ATTR_FSUUID 0x0001
3836

security/integrity/evm/evm_crypto.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ static DEFINE_MUTEX(mutex);
3737

3838
static unsigned long evm_set_key_flags;
3939

40+
static char * const evm_hmac = "hmac(sha1)";
41+
static char * const evm_hash = "sha1";
42+
4043
/**
4144
* evm_set_key() - set EVM HMAC key from the kernel
4245
* @key: pointer to a buffer with the key data

security/integrity/evm/evm_main.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@
3030

3131
int evm_initialized;
3232

33-
static char *integrity_status_msg[] = {
33+
static const char * const integrity_status_msg[] = {
3434
"pass", "pass_immutable", "fail", "no_label", "no_xattrs", "unknown"
3535
};
36-
char *evm_hmac = "hmac(sha1)";
37-
char *evm_hash = "sha1";
3836
int evm_hmac_attrs;
3937

4038
char *evm_config_xattrnames[] = {
@@ -126,6 +124,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
126124
struct evm_ima_xattr_data *xattr_data = NULL;
127125
struct evm_ima_xattr_data calc;
128126
enum integrity_status evm_status = INTEGRITY_PASS;
127+
struct inode *inode;
129128
int rc, xattr_len;
130129

131130
if (iint && (iint->evm_status == INTEGRITY_PASS ||
@@ -180,12 +179,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
180179
(const char *)xattr_data, xattr_len,
181180
calc.digest, sizeof(calc.digest));
182181
if (!rc) {
182+
inode = d_backing_inode(dentry);
183+
183184
if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
184185
if (iint)
185186
iint->flags |= EVM_IMMUTABLE_DIGSIG;
186187
evm_status = INTEGRITY_PASS_IMMUTABLE;
187-
} else if (!IS_RDONLY(d_backing_inode(dentry)) &&
188-
!IS_IMMUTABLE(d_backing_inode(dentry))) {
188+
} else if (!IS_RDONLY(inode) &&
189+
!(inode->i_sb->s_readonly_remount) &&
190+
!IS_IMMUTABLE(inode)) {
189191
evm_update_evmxattr(dentry, xattr_name,
190192
xattr_value,
191193
xattr_value_len);

security/integrity/iint.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ static void iint_free(struct integrity_iint_cache *iint)
7979
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
8080
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
8181
iint->ima_read_status = INTEGRITY_UNKNOWN;
82+
iint->ima_creds_status = INTEGRITY_UNKNOWN;
8283
iint->evm_status = INTEGRITY_UNKNOWN;
8384
iint->measured_pcrs = 0;
8485
kmem_cache_free(iint_cache, iint);
@@ -158,6 +159,7 @@ static void init_once(void *foo)
158159
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
159160
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
160161
iint->ima_read_status = INTEGRITY_UNKNOWN;
162+
iint->ima_creds_status = INTEGRITY_UNKNOWN;
161163
iint->evm_status = INTEGRITY_UNKNOWN;
162164
mutex_init(&iint->mutex);
163165
}

security/integrity/ima/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config IMA
1010
select CRYPTO_HASH_INFO
1111
select TCG_TPM if HAS_IOMEM && !UML
1212
select TCG_TIS if TCG_TPM && X86
13+
select TCG_CRB if TCG_TPM && ACPI
1314
select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES
1415
help
1516
The Trusted Computing Group(TCG) runtime Integrity

security/integrity/ima/ima.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
177177
hook(FILE_CHECK) \
178178
hook(MMAP_CHECK) \
179179
hook(BPRM_CHECK) \
180+
hook(CREDS_CHECK) \
180181
hook(POST_SETATTR) \
181182
hook(MODULE_CHECK) \
182183
hook(FIRMWARE_CHECK) \
@@ -191,8 +192,8 @@ enum ima_hooks {
191192
};
192193

193194
/* LIM API function definitions */
194-
int ima_get_action(struct inode *inode, int mask,
195-
enum ima_hooks func, int *pcr);
195+
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
196+
int mask, enum ima_hooks func, int *pcr);
196197
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
197198
int ima_collect_measurement(struct integrity_iint_cache *iint,
198199
struct file *file, void *buf, loff_t size,
@@ -212,8 +213,8 @@ void ima_free_template_entry(struct ima_template_entry *entry);
212213
const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
213214

214215
/* IMA policy related functions */
215-
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
216-
int flags, int *pcr);
216+
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
217+
enum ima_hooks func, int mask, int flags, int *pcr);
217218
void ima_init_policy(void);
218219
void ima_update_policy(void);
219220
void ima_update_policy_flag(void);

security/integrity/ima/ima_api.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
158158
/**
159159
* ima_get_action - appraise & measure decision based on policy.
160160
* @inode: pointer to inode to measure
161+
* @cred: pointer to credentials structure to validate
162+
* @secid: secid of the task being validated
161163
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
162164
* MAY_APPEND)
163165
* @func: caller identifier
@@ -166,20 +168,21 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
166168
* The policy is defined in terms of keypairs:
167169
* subj=, obj=, type=, func=, mask=, fsmagic=
168170
* subj,obj, and type: are LSM specific.
169-
* func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
171+
* func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
170172
* mask: contains the permission mask
171173
* fsmagic: hex value
172174
*
173175
* Returns IMA_MEASURE, IMA_APPRAISE mask.
174176
*
175177
*/
176-
int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr)
178+
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
179+
int mask, enum ima_hooks func, int *pcr)
177180
{
178181
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
179182

180183
flags &= ima_policy_flag;
181184

182-
return ima_match_policy(inode, func, mask, flags, pcr);
185+
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr);
183186
}
184187

185188
/*
@@ -308,33 +311,37 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
308311
const unsigned char *filename)
309312
{
310313
struct audit_buffer *ab;
311-
char hash[(iint->ima_hash->length * 2) + 1];
314+
char *hash;
312315
const char *algo_name = hash_algo_name[iint->ima_hash->algo];
313-
char algo_hash[sizeof(hash) + strlen(algo_name) + 2];
314316
int i;
315317

316318
if (iint->flags & IMA_AUDITED)
317319
return;
318320

321+
hash = kzalloc((iint->ima_hash->length * 2) + 1, GFP_KERNEL);
322+
if (!hash)
323+
return;
324+
319325
for (i = 0; i < iint->ima_hash->length; i++)
320326
hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
321327
hash[i * 2] = '\0';
322328

323329
ab = audit_log_start(current->audit_context, GFP_KERNEL,
324330
AUDIT_INTEGRITY_RULE);
325331
if (!ab)
326-
return;
332+
goto out;
327333

328334
audit_log_format(ab, "file=");
329335
audit_log_untrustedstring(ab, filename);
330-
audit_log_format(ab, " hash=");
331-
snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash);
332-
audit_log_untrustedstring(ab, algo_hash);
336+
audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash);
333337

334338
audit_log_task_info(ab, current);
335339
audit_log_end(ab);
336340

337341
iint->flags |= IMA_AUDITED;
342+
out:
343+
kfree(hash);
344+
return;
338345
}
339346

340347
/*

0 commit comments

Comments
 (0)