From: Greg Kroah-Hartman Date: Thu, 19 Jun 2014 02:41:51 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.4.95~44 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d4aae911b92888ca33061d03a545da5ec7e240dd;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: evm-prohibit-userspace-writing-security.evm-hmac-value.patch ima-audit-log-files-opened-with-o_direct-flag.patch ima-introduce-ima_kernel_read.patch --- diff --git a/queue-3.14/evm-prohibit-userspace-writing-security.evm-hmac-value.patch b/queue-3.14/evm-prohibit-userspace-writing-security.evm-hmac-value.patch new file mode 100644 index 00000000000..492ef639695 --- /dev/null +++ b/queue-3.14/evm-prohibit-userspace-writing-security.evm-hmac-value.patch @@ -0,0 +1,46 @@ +From 2fb1c9a4f2dbc2f0bd2431c7fa64d0b5483864e4 Mon Sep 17 00:00:00 2001 +From: Mimi Zohar +Date: Sun, 11 May 2014 00:05:23 -0400 +Subject: evm: prohibit userspace writing 'security.evm' HMAC value + +From: Mimi Zohar + +commit 2fb1c9a4f2dbc2f0bd2431c7fa64d0b5483864e4 upstream. + +Calculating the 'security.evm' HMAC value requires access to the +EVM encrypted key. Only the kernel should have access to it. This +patch prevents userspace tools(eg. setfattr, cp --preserve=xattr) +from setting/modifying the 'security.evm' HMAC value directly. + +Signed-off-by: Mimi Zohar +Signed-off-by: Greg Kroah-Hartman + +--- + security/integrity/evm/evm_main.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -285,12 +285,20 @@ out: + * @xattr_value: pointer to the new extended attribute value + * @xattr_value_len: pointer to the new extended attribute value length + * +- * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that +- * the current value is valid. ++ * Before allowing the 'security.evm' protected xattr to be updated, ++ * verify the existing value is valid. As only the kernel should have ++ * access to the EVM encrypted key needed to calculate the HMAC, prevent ++ * userspace from writing HMAC value. Writing 'security.evm' requires ++ * requires CAP_SYS_ADMIN privileges. + */ + int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len) + { ++ const struct evm_ima_xattr_data *xattr_data = xattr_value; ++ ++ if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0) ++ && (xattr_data->type == EVM_XATTR_HMAC)) ++ return -EPERM; + return evm_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); + } diff --git a/queue-3.14/ima-audit-log-files-opened-with-o_direct-flag.patch b/queue-3.14/ima-audit-log-files-opened-with-o_direct-flag.patch new file mode 100644 index 00000000000..eed5afe73d8 --- /dev/null +++ b/queue-3.14/ima-audit-log-files-opened-with-o_direct-flag.patch @@ -0,0 +1,147 @@ +From f9b2a735bdddf836214b5dca74f6ca7712e5a08c Mon Sep 17 00:00:00 2001 +From: Mimi Zohar +Date: Mon, 12 May 2014 09:28:11 -0400 +Subject: ima: audit log files opened with O_DIRECT flag + +From: Mimi Zohar + +commit f9b2a735bdddf836214b5dca74f6ca7712e5a08c upstream. + +Files are measured or appraised based on the IMA policy. When a +file, in policy, is opened with the O_DIRECT flag, a deadlock +occurs. + +The first attempt at resolving this lockdep temporarily removed the +O_DIRECT flag and restored it, after calculating the hash. The +second attempt introduced the O_DIRECT_HAVELOCK flag. Based on this +flag, do_blockdev_direct_IO() would skip taking the i_mutex a second +time. The third attempt, by Dmitry Kasatkin, resolves the i_mutex +locking issue, by re-introducing the IMA mutex, but uncovered +another problem. Reading a file with O_DIRECT flag set, writes +directly to userspace pages. A second patch allocates a user-space +like memory. This works for all IMA hooks, except ima_file_free(), +which is called on __fput() to recalculate the file hash. + +Until this last issue is addressed, do not 'collect' the +measurement for measuring, appraising, or auditing files opened +with the O_DIRECT flag set. Based on policy, permit or deny file +access. This patch defines a new IMA policy rule option named +'permit_directio'. Policy rules could be defined, based on LSM +or other criteria, to permit specific applications to open files +with the O_DIRECT flag set. + +Changelog v1: +- permit or deny file access based IMA policy rules + +Signed-off-by: Mimi Zohar +Acked-by: Dmitry Kasatkin +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/ABI/testing/ima_policy | 2 +- + security/integrity/ima/ima_api.c | 10 +++++++++- + security/integrity/ima/ima_main.c | 5 ++++- + security/integrity/ima/ima_policy.c | 6 +++++- + security/integrity/integrity.h | 1 + + 5 files changed, 20 insertions(+), 4 deletions(-) + +--- a/Documentation/ABI/testing/ima_policy ++++ b/Documentation/ABI/testing/ima_policy +@@ -23,7 +23,7 @@ Description: + [fowner]] + lsm: [[subj_user=] [subj_role=] [subj_type=] + [obj_user=] [obj_role=] [obj_type=]] +- option: [[appraise_type=]] ++ option: [[appraise_type=]] [permit_directio] + + base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] + mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] +--- a/security/integrity/ima/ima_api.c ++++ b/security/integrity/ima/ima_api.c +@@ -199,6 +199,7 @@ int ima_collect_measurement(struct integ + struct evm_ima_xattr_data **xattr_value, + int *xattr_len) + { ++ const char *audit_cause = "failed"; + struct inode *inode = file_inode(file); + const char *filename = file->f_dentry->d_name.name; + int result = 0; +@@ -213,6 +214,12 @@ int ima_collect_measurement(struct integ + if (!(iint->flags & IMA_COLLECTED)) { + u64 i_version = file_inode(file)->i_version; + ++ if (file->f_flags & O_DIRECT) { ++ audit_cause = "failed(directio)"; ++ result = -EACCES; ++ goto out; ++ } ++ + /* use default hash algorithm */ + hash.hdr.algo = ima_hash_algo; + +@@ -233,9 +240,10 @@ int ima_collect_measurement(struct integ + result = -ENOMEM; + } + } ++out: + if (result) + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, +- filename, "collect_data", "failed", ++ filename, "collect_data", audit_cause, + result, 0); + return result; + } +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -217,8 +217,11 @@ static int process_measurement(struct fi + xattr_ptr = &xattr_value; + + rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); +- if (rc != 0) ++ if (rc != 0) { ++ if (file->f_flags & O_DIRECT) ++ rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES; + goto out_digsig; ++ } + + pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename; + if (!pathname) +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -351,7 +351,7 @@ enum { + Opt_obj_user, Opt_obj_role, Opt_obj_type, + Opt_subj_user, Opt_subj_role, Opt_subj_type, + Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, +- Opt_appraise_type, Opt_fsuuid ++ Opt_appraise_type, Opt_fsuuid, Opt_permit_directio + }; + + static match_table_t policy_tokens = { +@@ -373,6 +373,7 @@ static match_table_t policy_tokens = { + {Opt_uid, "uid=%s"}, + {Opt_fowner, "fowner=%s"}, + {Opt_appraise_type, "appraise_type=%s"}, ++ {Opt_permit_directio, "permit_directio"}, + {Opt_err, NULL} + }; + +@@ -621,6 +622,9 @@ static int ima_parse_rule(char *rule, st + else + result = -EINVAL; + break; ++ case Opt_permit_directio: ++ entry->flags |= IMA_PERMIT_DIRECTIO; ++ break; + case Opt_err: + ima_log_string(ab, "UNKNOWN", p); + result = -EINVAL; +--- a/security/integrity/integrity.h ++++ b/security/integrity/integrity.h +@@ -30,6 +30,7 @@ + #define IMA_ACTION_FLAGS 0xff000000 + #define IMA_DIGSIG 0x01000000 + #define IMA_DIGSIG_REQUIRED 0x02000000 ++#define IMA_PERMIT_DIRECTIO 0x04000000 + + #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ + IMA_APPRAISE_SUBMASK) diff --git a/queue-3.14/ima-introduce-ima_kernel_read.patch b/queue-3.14/ima-introduce-ima_kernel_read.patch new file mode 100644 index 00000000000..3c1eaecb6ca --- /dev/null +++ b/queue-3.14/ima-introduce-ima_kernel_read.patch @@ -0,0 +1,169 @@ +From 0430e49b6e7c6b5e076be8fefdee089958c9adad Mon Sep 17 00:00:00 2001 +From: Dmitry Kasatkin +Date: Thu, 8 May 2014 14:03:22 +0300 +Subject: ima: introduce ima_kernel_read() + +From: Dmitry Kasatkin + +commit 0430e49b6e7c6b5e076be8fefdee089958c9adad upstream. + +Commit 8aac62706 "move exit_task_namespaces() outside of exit_notify" +introduced the kernel opps since the kernel v3.10, which happens when +Apparmor and IMA-appraisal are enabled at the same time. + +---------------------------------------------------------------------- +[ 106.750167] BUG: unable to handle kernel NULL pointer dereference at +0000000000000018 +[ 106.750221] IP: [] our_mnt+0x1a/0x30 +[ 106.750241] PGD 0 +[ 106.750254] Oops: 0000 [#1] SMP +[ 106.750272] Modules linked in: cuse parport_pc ppdev bnep rfcomm +bluetooth rpcsec_gss_krb5 nfsd auth_rpcgss nfs_acl nfs lockd sunrpc +fscache dm_crypt intel_rapl x86_pkg_temp_thermal intel_powerclamp +kvm_intel snd_hda_codec_hdmi kvm crct10dif_pclmul crc32_pclmul +ghash_clmulni_intel aesni_intel aes_x86_64 glue_helper lrw gf128mul +ablk_helper cryptd snd_hda_codec_realtek dcdbas snd_hda_intel +snd_hda_codec snd_hwdep snd_pcm snd_page_alloc snd_seq_midi +snd_seq_midi_event snd_rawmidi psmouse snd_seq microcode serio_raw +snd_timer snd_seq_device snd soundcore video lpc_ich coretemp mac_hid lp +parport mei_me mei nbd hid_generic e1000e usbhid ahci ptp hid libahci +pps_core +[ 106.750658] CPU: 6 PID: 1394 Comm: mysqld Not tainted 3.13.0-rc7-kds+ #15 +[ 106.750673] Hardware name: Dell Inc. OptiPlex 9010/0M9KCM, BIOS A08 +09/19/2012 +[ 106.750689] task: ffff8800de804920 ti: ffff880400fca000 task.ti: +ffff880400fca000 +[ 106.750704] RIP: 0010:[] [] +our_mnt+0x1a/0x30 +[ 106.750725] RSP: 0018:ffff880400fcba60 EFLAGS: 00010286 +[ 106.750738] RAX: 0000000000000000 RBX: 0000000000000100 RCX: +ffff8800d51523e7 +[ 106.750764] RDX: ffffffffffffffea RSI: ffff880400fcba34 RDI: +ffff880402d20020 +[ 106.750791] RBP: ffff880400fcbae0 R08: 0000000000000000 R09: +0000000000000001 +[ 106.750817] R10: 0000000000000000 R11: 0000000000000001 R12: +ffff8800d5152300 +[ 106.750844] R13: ffff8803eb8df510 R14: ffff880400fcbb28 R15: +ffff8800d51523e7 +[ 106.750871] FS: 0000000000000000(0000) GS:ffff88040d200000(0000) +knlGS:0000000000000000 +[ 106.750910] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 106.750935] CR2: 0000000000000018 CR3: 0000000001c0e000 CR4: +00000000001407e0 +[ 106.750962] Stack: +[ 106.750981] ffffffff813434eb ffff880400fcbb20 ffff880400fcbb18 +0000000000000000 +[ 106.751037] ffff8800de804920 ffffffff8101b9b9 0001800000000000 +0000000000000100 +[ 106.751093] 0000010000000000 0000000000000002 000000000000000e +ffff8803eb8df500 +[ 106.751149] Call Trace: +[ 106.751172] [] ? aa_path_name+0x2ab/0x430 +[ 106.751199] [] ? sched_clock+0x9/0x10 +[ 106.751225] [] aa_path_perm+0x7d/0x170 +[ 106.751250] [] ? native_sched_clock+0x15/0x80 +[ 106.751276] [] aa_file_perm+0x33/0x40 +[ 106.751301] [] common_file_perm+0x8e/0xb0 +[ 106.751327] [] apparmor_file_permission+0x18/0x20 +[ 106.751355] [] security_file_permission+0x23/0xa0 +[ 106.751382] [] rw_verify_area+0x52/0xe0 +[ 106.751407] [] vfs_read+0x6d/0x170 +[ 106.751432] [] kernel_read+0x41/0x60 +[ 106.751457] [] ima_calc_file_hash+0x225/0x280 +[ 106.751483] [] ? ima_calc_file_hash+0x32/0x280 +[ 106.751509] [] ima_collect_measurement+0x9d/0x160 +[ 106.751536] [] ? trace_hardirqs_on+0xd/0x10 +[ 106.751562] [] ? ima_file_free+0x6c/0xd0 +[ 106.751587] [] ima_update_xattr+0x34/0x60 +[ 106.751612] [] ima_file_free+0xc0/0xd0 +[ 106.751637] [] __fput+0xd5/0x300 +[ 106.751662] [] ____fput+0xe/0x10 +[ 106.751687] [] task_work_run+0xc4/0xe0 +[ 106.751712] [] do_exit+0x2bd/0xa90 +[ 106.751738] [] ? retint_swapgs+0x13/0x1b +[ 106.751763] [] do_group_exit+0x4c/0xc0 +[ 106.751788] [] SyS_exit_group+0x14/0x20 +[ 106.751814] [] system_call_fastpath+0x1a/0x1f +[ 106.751839] Code: c3 0f 1f 44 00 00 55 48 89 e5 e8 22 fe ff ff 5d c3 +0f 1f 44 00 00 55 65 48 8b 04 25 c0 c9 00 00 48 8b 80 28 06 00 00 48 89 +e5 5d <48> 8b 40 18 48 39 87 c0 00 00 00 0f 94 c0 c3 0f 1f 80 00 00 00 +[ 106.752185] RIP [] our_mnt+0x1a/0x30 +[ 106.752214] RSP +[ 106.752236] CR2: 0000000000000018 +[ 106.752258] ---[ end trace 3c520748b4732721 ]--- +---------------------------------------------------------------------- + +The reason for the oops is that IMA-appraisal uses "kernel_read()" when +file is closed. kernel_read() honors LSM security hook which calls +Apparmor handler, which uses current->nsproxy->mnt_ns. The 'guilty' +commit changed the order of cleanup code so that nsproxy->mnt_ns was +not already available for Apparmor. + +Discussion about the issue with Al Viro and Eric W. Biederman suggested +that kernel_read() is too high-level for IMA. Another issue, except +security checking, that was identified is mandatory locking. kernel_read +honors it as well and it might prevent IMA from calculating necessary hash. +It was suggested to use simplified version of the function without security +and locking checks. + +This patch introduces special version ima_kernel_read(), which skips security +and mandatory locking checking. It prevents the kernel oops to happen. + +Signed-off-by: Dmitry Kasatkin +Suggested-by: Eric W. Biederman +Signed-off-by: Mimi Zohar +Signed-off-by: Greg Kroah-Hartman + +--- + security/integrity/ima/ima_crypto.c | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +--- a/security/integrity/ima/ima_crypto.c ++++ b/security/integrity/ima/ima_crypto.c +@@ -25,6 +25,36 @@ + + static struct crypto_shash *ima_shash_tfm; + ++/** ++ * ima_kernel_read - read file content ++ * ++ * This is a function for reading file content instead of kernel_read(). ++ * It does not perform locking checks to ensure it cannot be blocked. ++ * It does not perform security checks because it is irrelevant for IMA. ++ * ++ */ ++static int ima_kernel_read(struct file *file, loff_t offset, ++ char *addr, unsigned long count) ++{ ++ mm_segment_t old_fs; ++ char __user *buf = addr; ++ ssize_t ret; ++ ++ if (!(file->f_mode & FMODE_READ)) ++ return -EBADF; ++ if (!file->f_op->read && !file->f_op->aio_read) ++ return -EINVAL; ++ ++ old_fs = get_fs(); ++ set_fs(get_ds()); ++ if (file->f_op->read) ++ ret = file->f_op->read(file, buf, count, &offset); ++ else ++ ret = do_sync_read(file, buf, count, &offset); ++ set_fs(old_fs); ++ return ret; ++} ++ + int ima_init_crypto(void) + { + long rc; +@@ -98,7 +128,7 @@ static int ima_calc_file_hash_tfm(struct + while (offset < i_size) { + int rbuf_len; + +- rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); ++ rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE); + if (rbuf_len < 0) { + rc = rbuf_len; + break; diff --git a/queue-3.14/series b/queue-3.14/series index 572bda16da8..133448f52c3 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -1,3 +1,6 @@ rtc-rtc-at91rm9200-fix-infinite-wait-for-ackupd-irq.patch target-fix-null-pointer-dereference-for-xcopy-in-target_put_sess_cmd.patch iscsi-target-reject-mutual-authentication-with-reflected-chap_c.patch +ima-audit-log-files-opened-with-o_direct-flag.patch +ima-introduce-ima_kernel_read.patch +evm-prohibit-userspace-writing-security.evm-hmac-value.patch