Skip to content

Commit

Permalink
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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
  • Loading branch information
torvalds committed Apr 7, 2018
2 parents 4b3f1a1 + ab60368 commit f8cf2f1
Show file tree
Hide file tree
Showing 22 changed files with 227 additions and 70 deletions.
2 changes: 1 addition & 1 deletion Documentation/ABI/testing/ima_policy
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Description:
[obj_user=] [obj_role=] [obj_type=]]
option: [[appraise_type=]] [permit_directio]

base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
Expand Down
8 changes: 7 additions & 1 deletion Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,8 @@

ima_policy= [IMA]
The builtin policies to load during IMA setup.
Format: "tcb | appraise_tcb | secure_boot"
Format: "tcb | appraise_tcb | secure_boot |
fail_securely"

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

The "fail_securely" policy forces file signature
verification failure also on privileged mounted
filesystems with the SB_I_UNVERIFIABLE_SIGNATURE
flag.

ima_tcb [IMA] Deprecated. Use ima_policy= instead.
Load a policy which meets the needs of the Trusted
Computing Base. This means IMA will measure all
Expand Down
3 changes: 3 additions & 0 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,9 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_time_gran = 1;
sb->s_export_op = &fuse_export_operations;
sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
if (sb->s_user_ns != &init_user_ns)
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;

file = fget(d.fd);
err = -EINVAL;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,8 @@ extern int send_sigurg(struct fown_struct *fown);

/* sb->s_iflags to limit user namespace mounts */
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
#define SB_I_IMA_UNVERIFIABLE_SIGNATURE 0x00000020
#define SB_I_UNTRUSTED_MOUNTER 0x00000040

/* Possible states of 'frozen' field */
enum {
Expand Down
6 changes: 6 additions & 0 deletions include/linux/lsm_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@
* @new points to the new credentials.
* @old points to the original credentials.
* Transfer data from original creds to new creds
* @cred_getsecid:
* Retrieve the security identifier of the cred structure @c
* @c contains the credentials, secid will be placed into @secid.
* In case of failure, @secid will be set to zero.
* @kernel_act_as:
* Set the credentials for a kernel service to act as (subjective context).
* @new points to the credentials to be modified.
Expand Down Expand Up @@ -1569,6 +1573,7 @@ union security_list_options {
int (*cred_prepare)(struct cred *new, const struct cred *old,
gfp_t gfp);
void (*cred_transfer)(struct cred *new, const struct cred *old);
void (*cred_getsecid)(const struct cred *c, u32 *secid);
int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name);
Expand Down Expand Up @@ -1858,6 +1863,7 @@ struct security_hook_heads {
struct hlist_head cred_free;
struct hlist_head cred_prepare;
struct hlist_head cred_transfer;
struct hlist_head cred_getsecid;
struct hlist_head kernel_act_as;
struct hlist_head kernel_create_files_as;
struct hlist_head kernel_read_file;
Expand Down
1 change: 1 addition & 0 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
void security_cred_free(struct cred *cred);
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
void security_transfer_creds(struct cred *new, const struct cred *old);
void security_cred_getsecid(const struct cred *c, u32 *secid);
int security_kernel_act_as(struct cred *new, u32 secid);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(char *kmod_name);
Expand Down
2 changes: 0 additions & 2 deletions security/integrity/evm/evm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
EVM_ALLOW_METADATA_WRITES)

extern int evm_initialized;
extern char *evm_hmac;
extern char *evm_hash;

#define EVM_ATTR_FSUUID 0x0001

Expand Down
3 changes: 3 additions & 0 deletions security/integrity/evm/evm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ static DEFINE_MUTEX(mutex);

static unsigned long evm_set_key_flags;

static char * const evm_hmac = "hmac(sha1)";
static char * const evm_hash = "sha1";

/**
* evm_set_key() - set EVM HMAC key from the kernel
* @key: pointer to a buffer with the key data
Expand Down
12 changes: 7 additions & 5 deletions security/integrity/evm/evm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@

int evm_initialized;

static char *integrity_status_msg[] = {
static const char * const integrity_status_msg[] = {
"pass", "pass_immutable", "fail", "no_label", "no_xattrs", "unknown"
};
char *evm_hmac = "hmac(sha1)";
char *evm_hash = "sha1";
int evm_hmac_attrs;

char *evm_config_xattrnames[] = {
Expand Down Expand Up @@ -126,6 +124,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
struct evm_ima_xattr_data *xattr_data = NULL;
struct evm_ima_xattr_data calc;
enum integrity_status evm_status = INTEGRITY_PASS;
struct inode *inode;
int rc, xattr_len;

if (iint && (iint->evm_status == INTEGRITY_PASS ||
Expand Down Expand Up @@ -180,12 +179,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
(const char *)xattr_data, xattr_len,
calc.digest, sizeof(calc.digest));
if (!rc) {
inode = d_backing_inode(dentry);

if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
if (iint)
iint->flags |= EVM_IMMUTABLE_DIGSIG;
evm_status = INTEGRITY_PASS_IMMUTABLE;
} else if (!IS_RDONLY(d_backing_inode(dentry)) &&
!IS_IMMUTABLE(d_backing_inode(dentry))) {
} else if (!IS_RDONLY(inode) &&
!(inode->i_sb->s_readonly_remount) &&
!IS_IMMUTABLE(inode)) {
evm_update_evmxattr(dentry, xattr_name,
xattr_value,
xattr_value_len);
Expand Down
2 changes: 2 additions & 0 deletions security/integrity/iint.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ static void iint_free(struct integrity_iint_cache *iint)
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->ima_creds_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
iint->measured_pcrs = 0;
kmem_cache_free(iint_cache, iint);
Expand Down Expand Up @@ -158,6 +159,7 @@ static void init_once(void *foo)
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->ima_creds_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
mutex_init(&iint->mutex);
}
Expand Down
1 change: 1 addition & 0 deletions security/integrity/ima/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ config IMA
select CRYPTO_HASH_INFO
select TCG_TPM if HAS_IOMEM && !UML
select TCG_TIS if TCG_TPM && X86
select TCG_CRB if TCG_TPM && ACPI
select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES
help
The Trusted Computing Group(TCG) runtime Integrity
Expand Down
9 changes: 5 additions & 4 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
hook(FILE_CHECK) \
hook(MMAP_CHECK) \
hook(BPRM_CHECK) \
hook(CREDS_CHECK) \
hook(POST_SETATTR) \
hook(MODULE_CHECK) \
hook(FIRMWARE_CHECK) \
Expand All @@ -191,8 +192,8 @@ enum ima_hooks {
};

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

/* IMA policy related functions */
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
int flags, int *pcr);
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
enum ima_hooks func, int mask, int flags, int *pcr);
void ima_init_policy(void);
void ima_update_policy(void);
void ima_update_policy_flag(void);
Expand Down
25 changes: 16 additions & 9 deletions security/integrity/ima/ima_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
/**
* ima_get_action - appraise & measure decision based on policy.
* @inode: pointer to inode to measure
* @cred: pointer to credentials structure to validate
* @secid: secid of the task being validated
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
* MAY_APPEND)
* @func: caller identifier
Expand All @@ -166,20 +168,21 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
* The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic=
* subj,obj, and type: are LSM specific.
* func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
* func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
* mask: contains the permission mask
* fsmagic: hex value
*
* Returns IMA_MEASURE, IMA_APPRAISE mask.
*
*/
int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr)
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
int mask, enum ima_hooks func, int *pcr)
{
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;

flags &= ima_policy_flag;

return ima_match_policy(inode, func, mask, flags, pcr);
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr);
}

/*
Expand Down Expand Up @@ -308,33 +311,37 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename)
{
struct audit_buffer *ab;
char hash[(iint->ima_hash->length * 2) + 1];
char *hash;
const char *algo_name = hash_algo_name[iint->ima_hash->algo];
char algo_hash[sizeof(hash) + strlen(algo_name) + 2];
int i;

if (iint->flags & IMA_AUDITED)
return;

hash = kzalloc((iint->ima_hash->length * 2) + 1, GFP_KERNEL);
if (!hash)
return;

for (i = 0; i < iint->ima_hash->length; i++)
hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
hash[i * 2] = '\0';

ab = audit_log_start(current->audit_context, GFP_KERNEL,
AUDIT_INTEGRITY_RULE);
if (!ab)
return;
goto out;

audit_log_format(ab, "file=");
audit_log_untrustedstring(ab, filename);
audit_log_format(ab, " hash=");
snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash);
audit_log_untrustedstring(ab, algo_hash);
audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash);

audit_log_task_info(ab, current);
audit_log_end(ab);

iint->flags |= IMA_AUDITED;
out:
kfree(hash);
return;
}

/*
Expand Down
Loading

0 comments on commit f8cf2f1

Please sign in to comment.