Merge 4.14.50 into android-4.14
Changes in 4.14.50
netfilter: nf_tables: fix NULL pointer dereference on nft_ct_helper_obj_dump()
blkdev_report_zones_ioctl(): Use vmalloc() to allocate large buffers
af_key: Always verify length of provided sadb_key
gpio: No NULL owner
KVM: X86: Fix reserved bits check for MOV to CR3
KVM: x86: introduce linear_{read,write}_system
kvm: nVMX: Enforce cpl=0 for VMX instructions
KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and kvm_write_guest_virt_system
staging: android: ion: Switch to pr_warn_once in ion_buffer_destroy
NFC: pn533: don't send USB data off of the stack
usbip: vhci_sysfs: fix potential Spectre v1
usb-storage: Add support for FL_ALWAYS_SYNC flag in the UAS driver
usb-storage: Add compatibility quirk flags for G-Technologies G-Drive
Input: xpad - add GPD Win 2 Controller USB IDs
phy: qcom-qusb2: Fix crash if nvmem cell not specified
usb: gadget: function: printer: avoid wrong list handling in printer_write()
usb: gadget: udc: renesas_usb3: disable the controller's irqs for reconnecting
serial: sh-sci: Stop using printk format %pCr
tty/serial: atmel: use port->name as name in request_irq()
serial: samsung: fix maxburst parameter for DMA transactions
serial: 8250: omap: Fix idling of clocks for unused uarts
vmw_balloon: fixing double free when batching mode is off
tty: pl011: Avoid spuriously stuck-off interrupts
kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access
Input: goodix - add new ACPI id for GPD Win 2 touch screen
Input: elan_i2c - add ELAN0612 (Lenovo v330 14IKB) ACPI ID
crypto: caam - strip input zeros from RSA input buffer
crypto: caam - fix DMA mapping dir for generated IV
crypto: caam - fix IV DMA mapping and updating
crypto: caam/qi - fix IV DMA mapping and updating
crypto: caam - fix size of RSA prime factor q
crypto: cavium - Fix fallout from CONFIG_VMAP_STACK
crypto: cavium - Limit result reading attempts
crypto: vmx - Remove overly verbose printk from AES init routines
crypto: vmx - Remove overly verbose printk from AES XTS init
crypto: omap-sham - fix memleak
Linux 4.14.50
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 14
|
||||
SUBLEVEL = 49
|
||||
SUBLEVEL = 50
|
||||
EXTRAVERSION =
|
||||
NAME = Petit Gorille
|
||||
|
||||
|
||||
@@ -107,11 +107,12 @@ struct x86_emulate_ops {
|
||||
* @addr: [IN ] Linear address from which to read.
|
||||
* @val: [OUT] Value read from memory, zero-extended to 'u_long'.
|
||||
* @bytes: [IN ] Number of bytes to read from memory.
|
||||
* @system:[IN ] Whether the access is forced to be at CPL0.
|
||||
*/
|
||||
int (*read_std)(struct x86_emulate_ctxt *ctxt,
|
||||
unsigned long addr, void *val,
|
||||
unsigned int bytes,
|
||||
struct x86_exception *fault);
|
||||
struct x86_exception *fault, bool system);
|
||||
|
||||
/*
|
||||
* read_phys: Read bytes of standard (non-emulated/special) memory.
|
||||
@@ -129,10 +130,11 @@ struct x86_emulate_ops {
|
||||
* @addr: [IN ] Linear address to which to write.
|
||||
* @val: [OUT] Value write to memory, zero-extended to 'u_long'.
|
||||
* @bytes: [IN ] Number of bytes to write to memory.
|
||||
* @system:[IN ] Whether the access is forced to be at CPL0.
|
||||
*/
|
||||
int (*write_std)(struct x86_emulate_ctxt *ctxt,
|
||||
unsigned long addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *fault);
|
||||
struct x86_exception *fault, bool system);
|
||||
/*
|
||||
* fetch: Read bytes of standard (non-emulated/special) memory.
|
||||
* Used for instruction fetch.
|
||||
|
||||
@@ -811,6 +811,19 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
|
||||
return assign_eip_near(ctxt, ctxt->_eip + rel);
|
||||
}
|
||||
|
||||
static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear,
|
||||
void *data, unsigned size)
|
||||
{
|
||||
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true);
|
||||
}
|
||||
|
||||
static int linear_write_system(struct x86_emulate_ctxt *ctxt,
|
||||
ulong linear, void *data,
|
||||
unsigned int size)
|
||||
{
|
||||
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true);
|
||||
}
|
||||
|
||||
static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
|
||||
struct segmented_address addr,
|
||||
void *data,
|
||||
@@ -822,7 +835,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
|
||||
rc = linearize(ctxt, addr, size, false, &linear);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
|
||||
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false);
|
||||
}
|
||||
|
||||
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
|
||||
@@ -836,7 +849,7 @@ static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
|
||||
rc = linearize(ctxt, addr, size, true, &linear);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
|
||||
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1509,8 +1522,7 @@ static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||
return emulate_gp(ctxt, index << 3 | 0x2);
|
||||
|
||||
addr = dt.address + index * 8;
|
||||
return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
|
||||
&ctxt->exception);
|
||||
return linear_read_system(ctxt, addr, desc, sizeof *desc);
|
||||
}
|
||||
|
||||
static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
|
||||
@@ -1573,8 +1585,7 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
|
||||
return ctxt->ops->read_std(ctxt, *desc_addr_p, desc, sizeof(*desc),
|
||||
&ctxt->exception);
|
||||
return linear_read_system(ctxt, *desc_addr_p, desc, sizeof(*desc));
|
||||
}
|
||||
|
||||
/* allowed just for 8 bytes segments */
|
||||
@@ -1588,8 +1599,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
|
||||
return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc,
|
||||
&ctxt->exception);
|
||||
return linear_write_system(ctxt, addr, desc, sizeof *desc);
|
||||
}
|
||||
|
||||
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||
@@ -1750,8 +1760,7 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||
return ret;
|
||||
}
|
||||
} else if (ctxt->mode == X86EMUL_MODE_PROT64) {
|
||||
ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3,
|
||||
sizeof(base3), &ctxt->exception);
|
||||
ret = linear_read_system(ctxt, desc_addr+8, &base3, sizeof(base3));
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
if (emul_is_noncanonical_address(get_desc_base(&seg_desc) |
|
||||
@@ -2064,11 +2073,11 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
|
||||
eip_addr = dt.address + (irq << 2);
|
||||
cs_addr = dt.address + (irq << 2) + 2;
|
||||
|
||||
rc = ops->read_std(ctxt, cs_addr, &cs, 2, &ctxt->exception);
|
||||
rc = linear_read_system(ctxt, cs_addr, &cs, 2);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
|
||||
rc = ops->read_std(ctxt, eip_addr, &eip, 2, &ctxt->exception);
|
||||
rc = linear_read_system(ctxt, eip_addr, &eip, 2);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
|
||||
@@ -2912,12 +2921,12 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
|
||||
#ifdef CONFIG_X86_64
|
||||
base |= ((u64)base3) << 32;
|
||||
#endif
|
||||
r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL);
|
||||
r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true);
|
||||
if (r != X86EMUL_CONTINUE)
|
||||
return false;
|
||||
if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
|
||||
return false;
|
||||
r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL);
|
||||
r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true);
|
||||
if (r != X86EMUL_CONTINUE)
|
||||
return false;
|
||||
if ((perm >> bit_idx) & mask)
|
||||
@@ -3046,35 +3055,30 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
|
||||
u16 tss_selector, u16 old_tss_sel,
|
||||
ulong old_tss_base, struct desc_struct *new_desc)
|
||||
{
|
||||
const struct x86_emulate_ops *ops = ctxt->ops;
|
||||
struct tss_segment_16 tss_seg;
|
||||
int ret;
|
||||
u32 new_tss_base = get_desc_base(new_desc);
|
||||
|
||||
ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
|
||||
&ctxt->exception);
|
||||
ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
save_state_to_tss16(ctxt, &tss_seg);
|
||||
|
||||
ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
|
||||
&ctxt->exception);
|
||||
ret = linear_write_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg,
|
||||
&ctxt->exception);
|
||||
ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
if (old_tss_sel != 0xffff) {
|
||||
tss_seg.prev_task_link = old_tss_sel;
|
||||
|
||||
ret = ops->write_std(ctxt, new_tss_base,
|
||||
&tss_seg.prev_task_link,
|
||||
sizeof tss_seg.prev_task_link,
|
||||
&ctxt->exception);
|
||||
ret = linear_write_system(ctxt, new_tss_base,
|
||||
&tss_seg.prev_task_link,
|
||||
sizeof tss_seg.prev_task_link);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
}
|
||||
@@ -3190,38 +3194,34 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
|
||||
u16 tss_selector, u16 old_tss_sel,
|
||||
ulong old_tss_base, struct desc_struct *new_desc)
|
||||
{
|
||||
const struct x86_emulate_ops *ops = ctxt->ops;
|
||||
struct tss_segment_32 tss_seg;
|
||||
int ret;
|
||||
u32 new_tss_base = get_desc_base(new_desc);
|
||||
u32 eip_offset = offsetof(struct tss_segment_32, eip);
|
||||
u32 ldt_sel_offset = offsetof(struct tss_segment_32, ldt_selector);
|
||||
|
||||
ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
|
||||
&ctxt->exception);
|
||||
ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
save_state_to_tss32(ctxt, &tss_seg);
|
||||
|
||||
/* Only GP registers and segment selectors are saved */
|
||||
ret = ops->write_std(ctxt, old_tss_base + eip_offset, &tss_seg.eip,
|
||||
ldt_sel_offset - eip_offset, &ctxt->exception);
|
||||
ret = linear_write_system(ctxt, old_tss_base + eip_offset, &tss_seg.eip,
|
||||
ldt_sel_offset - eip_offset);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg,
|
||||
&ctxt->exception);
|
||||
ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
|
||||
if (old_tss_sel != 0xffff) {
|
||||
tss_seg.prev_task_link = old_tss_sel;
|
||||
|
||||
ret = ops->write_std(ctxt, new_tss_base,
|
||||
&tss_seg.prev_task_link,
|
||||
sizeof tss_seg.prev_task_link,
|
||||
&ctxt->exception);
|
||||
ret = linear_write_system(ctxt, new_tss_base,
|
||||
&tss_seg.prev_task_link,
|
||||
sizeof tss_seg.prev_task_link);
|
||||
if (ret != X86EMUL_CONTINUE)
|
||||
return ret;
|
||||
}
|
||||
@@ -4152,7 +4152,9 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
|
||||
maxphyaddr = eax & 0xff;
|
||||
else
|
||||
maxphyaddr = 36;
|
||||
rsvd = rsvd_bits(maxphyaddr, 62);
|
||||
rsvd = rsvd_bits(maxphyaddr, 63);
|
||||
if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_PCIDE)
|
||||
rsvd &= ~CR3_PCID_INVD;
|
||||
}
|
||||
|
||||
if (new_val & rsvd)
|
||||
|
||||
@@ -7317,8 +7317,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
|
||||
vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
|
||||
return 1;
|
||||
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer,
|
||||
sizeof(*vmpointer), &e)) {
|
||||
if (kvm_read_guest_virt(vcpu, gva, vmpointer, sizeof(*vmpointer), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
@@ -7399,6 +7398,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* CPL=0 must be checked manually. */
|
||||
if (vmx_get_cpl(vcpu)) {
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vmx->nested.vmxon) {
|
||||
nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
@@ -7458,6 +7463,11 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vmx_get_cpl(vcpu)) {
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!to_vmx(vcpu)->nested.vmxon) {
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
return 0;
|
||||
@@ -7790,9 +7800,9 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
|
||||
if (get_vmx_mem_address(vcpu, exit_qualification,
|
||||
vmx_instruction_info, true, &gva))
|
||||
return 1;
|
||||
/* _system ok, as hardware has verified cpl=0 */
|
||||
kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
|
||||
&field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
|
||||
/* _system ok, nested_vmx_check_permission has verified cpl=0 */
|
||||
kvm_write_guest_virt_system(vcpu, gva, &field_value,
|
||||
(is_long_mode(vcpu) ? 8 : 4), NULL);
|
||||
}
|
||||
|
||||
nested_vmx_succeed(vcpu);
|
||||
@@ -7828,8 +7838,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
|
||||
if (get_vmx_mem_address(vcpu, exit_qualification,
|
||||
vmx_instruction_info, false, &gva))
|
||||
return 1;
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
|
||||
&field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
|
||||
if (kvm_read_guest_virt(vcpu, gva, &field_value,
|
||||
(is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
@@ -7933,10 +7943,10 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
|
||||
if (get_vmx_mem_address(vcpu, exit_qualification,
|
||||
vmx_instruction_info, true, &vmcs_gva))
|
||||
return 1;
|
||||
/* ok to use *_system, as hardware has verified cpl=0 */
|
||||
if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
|
||||
(void *)&to_vmx(vcpu)->nested.current_vmptr,
|
||||
sizeof(u64), &e)) {
|
||||
/* *_system ok, nested_vmx_check_permission has verified cpl=0 */
|
||||
if (kvm_write_guest_virt_system(vcpu, vmcs_gva,
|
||||
(void *)&to_vmx(vcpu)->nested.current_vmptr,
|
||||
sizeof(u64), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
@@ -7983,8 +7993,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
||||
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
|
||||
vmx_instruction_info, false, &gva))
|
||||
return 1;
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
|
||||
sizeof(operand), &e)) {
|
||||
if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
@@ -8048,8 +8057,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
||||
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
|
||||
vmx_instruction_info, false, &gva))
|
||||
return 1;
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
|
||||
sizeof(operand), &e)) {
|
||||
if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -836,7 +836,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
|
||||
}
|
||||
|
||||
if (is_long_mode(vcpu) &&
|
||||
(cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 62)))
|
||||
(cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)))
|
||||
return 1;
|
||||
else if (is_pae(vcpu) && is_paging(vcpu) &&
|
||||
!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
|
||||
@@ -4492,11 +4492,10 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
|
||||
int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
|
||||
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
|
||||
@@ -4504,12 +4503,17 @@ int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
|
||||
|
||||
static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception)
|
||||
static int emulator_read_std(struct x86_emulate_ctxt *ctxt,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception, bool system)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
|
||||
u32 access = 0;
|
||||
|
||||
if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
|
||||
access |= PFERR_USER_MASK;
|
||||
|
||||
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception);
|
||||
}
|
||||
|
||||
static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
|
||||
@@ -4521,18 +4525,16 @@ static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
|
||||
return r < 0 ? X86EMUL_IO_NEEDED : X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
|
||||
gva_t addr, void *val,
|
||||
unsigned int bytes,
|
||||
struct x86_exception *exception)
|
||||
static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
|
||||
struct kvm_vcpu *vcpu, u32 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
void *data = val;
|
||||
int r = X86EMUL_CONTINUE;
|
||||
|
||||
while (bytes) {
|
||||
gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr,
|
||||
PFERR_WRITE_MASK,
|
||||
access,
|
||||
exception);
|
||||
unsigned offset = addr & (PAGE_SIZE-1);
|
||||
unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
|
||||
@@ -4553,6 +4555,27 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val,
|
||||
unsigned int bytes, struct x86_exception *exception,
|
||||
bool system)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
u32 access = PFERR_WRITE_MASK;
|
||||
|
||||
if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
|
||||
access |= PFERR_USER_MASK;
|
||||
|
||||
return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
|
||||
access, exception);
|
||||
}
|
||||
|
||||
int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
|
||||
unsigned int bytes, struct x86_exception *exception)
|
||||
{
|
||||
return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
|
||||
PFERR_WRITE_MASK, exception);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
|
||||
|
||||
static int vcpu_is_mmio_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
|
||||
@@ -5287,8 +5310,8 @@ static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_fla
|
||||
static const struct x86_emulate_ops emulate_ops = {
|
||||
.read_gpr = emulator_read_gpr,
|
||||
.write_gpr = emulator_write_gpr,
|
||||
.read_std = kvm_read_guest_virt_system,
|
||||
.write_std = kvm_write_guest_virt_system,
|
||||
.read_std = emulator_read_std,
|
||||
.write_std = emulator_write_std,
|
||||
.read_phys = kvm_read_guest_phys_system,
|
||||
.fetch = kvm_fetch_guest_virt,
|
||||
.read_emulated = emulator_read_emulated,
|
||||
|
||||
@@ -213,11 +213,11 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
|
||||
void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr);
|
||||
u64 get_kvmclock_ns(struct kvm *kvm);
|
||||
|
||||
int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
|
||||
int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception);
|
||||
|
||||
int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
|
||||
int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception);
|
||||
|
||||
|
||||
@@ -286,7 +286,11 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
if (!rep.nr_zones)
|
||||
return -EINVAL;
|
||||
|
||||
zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL);
|
||||
if (rep.nr_zones > INT_MAX / sizeof(struct blk_zone))
|
||||
return -ERANGE;
|
||||
|
||||
zones = kvmalloc(rep.nr_zones * sizeof(struct blk_zone),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!zones)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -308,7 +312,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(zones);
|
||||
kvfree(zones);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -735,15 +735,18 @@ struct aead_edesc {
|
||||
* @src_nents: number of segments in input s/w scatterlist
|
||||
* @dst_nents: number of segments in output s/w scatterlist
|
||||
* @iv_dma: dma address of iv for checking continuity and link table
|
||||
* @iv_dir: DMA mapping direction for IV
|
||||
* @sec4_sg_bytes: length of dma mapped sec4_sg space
|
||||
* @sec4_sg_dma: bus physical mapped address of h/w link table
|
||||
* @sec4_sg: pointer to h/w link table
|
||||
* @hw_desc: the h/w job descriptor followed by any referenced link tables
|
||||
* and IV
|
||||
*/
|
||||
struct ablkcipher_edesc {
|
||||
int src_nents;
|
||||
int dst_nents;
|
||||
dma_addr_t iv_dma;
|
||||
enum dma_data_direction iv_dir;
|
||||
int sec4_sg_bytes;
|
||||
dma_addr_t sec4_sg_dma;
|
||||
struct sec4_sg_entry *sec4_sg;
|
||||
@@ -753,7 +756,8 @@ struct ablkcipher_edesc {
|
||||
static void caam_unmap(struct device *dev, struct scatterlist *src,
|
||||
struct scatterlist *dst, int src_nents,
|
||||
int dst_nents,
|
||||
dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma,
|
||||
dma_addr_t iv_dma, int ivsize,
|
||||
enum dma_data_direction iv_dir, dma_addr_t sec4_sg_dma,
|
||||
int sec4_sg_bytes)
|
||||
{
|
||||
if (dst != src) {
|
||||
@@ -765,7 +769,7 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
|
||||
}
|
||||
|
||||
if (iv_dma)
|
||||
dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev, iv_dma, ivsize, iv_dir);
|
||||
if (sec4_sg_bytes)
|
||||
dma_unmap_single(dev, sec4_sg_dma, sec4_sg_bytes,
|
||||
DMA_TO_DEVICE);
|
||||
@@ -776,7 +780,7 @@ static void aead_unmap(struct device *dev,
|
||||
struct aead_request *req)
|
||||
{
|
||||
caam_unmap(dev, req->src, req->dst,
|
||||
edesc->src_nents, edesc->dst_nents, 0, 0,
|
||||
edesc->src_nents, edesc->dst_nents, 0, 0, DMA_NONE,
|
||||
edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
|
||||
}
|
||||
|
||||
@@ -789,7 +793,7 @@ static void ablkcipher_unmap(struct device *dev,
|
||||
|
||||
caam_unmap(dev, req->src, req->dst,
|
||||
edesc->src_nents, edesc->dst_nents,
|
||||
edesc->iv_dma, ivsize,
|
||||
edesc->iv_dma, ivsize, edesc->iv_dir,
|
||||
edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
|
||||
}
|
||||
|
||||
@@ -878,6 +882,18 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
|
||||
scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
|
||||
ivsize, 0);
|
||||
|
||||
/* In case initial IV was generated, copy it in GIVCIPHER request */
|
||||
if (edesc->iv_dir == DMA_FROM_DEVICE) {
|
||||
u8 *iv;
|
||||
struct skcipher_givcrypt_request *greq;
|
||||
|
||||
greq = container_of(req, struct skcipher_givcrypt_request,
|
||||
creq);
|
||||
iv = (u8 *)edesc->hw_desc + desc_bytes(edesc->hw_desc) +
|
||||
edesc->sec4_sg_bytes;
|
||||
memcpy(greq->giv, iv, ivsize);
|
||||
}
|
||||
|
||||
kfree(edesc);
|
||||
|
||||
ablkcipher_request_complete(req, err);
|
||||
@@ -888,10 +904,10 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
|
||||
{
|
||||
struct ablkcipher_request *req = context;
|
||||
struct ablkcipher_edesc *edesc;
|
||||
#ifdef DEBUG
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
|
||||
#ifdef DEBUG
|
||||
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
|
||||
#endif
|
||||
|
||||
@@ -909,14 +925,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
|
||||
edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
|
||||
|
||||
ablkcipher_unmap(jrdev, edesc, req);
|
||||
|
||||
/*
|
||||
* The crypto API expects us to set the IV (req->info) to the last
|
||||
* ciphertext block.
|
||||
*/
|
||||
scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize,
|
||||
ivsize, 0);
|
||||
|
||||
kfree(edesc);
|
||||
|
||||
ablkcipher_request_complete(req, err);
|
||||
@@ -1057,15 +1065,14 @@ static void init_authenc_job(struct aead_request *req,
|
||||
*/
|
||||
static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
|
||||
struct ablkcipher_edesc *edesc,
|
||||
struct ablkcipher_request *req,
|
||||
bool iv_contig)
|
||||
struct ablkcipher_request *req)
|
||||
{
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
u32 *desc = edesc->hw_desc;
|
||||
u32 out_options = 0, in_options;
|
||||
dma_addr_t dst_dma, src_dma;
|
||||
int len, sec4_sg_index = 0;
|
||||
u32 out_options = 0;
|
||||
dma_addr_t dst_dma;
|
||||
int len;
|
||||
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
|
||||
@@ -1081,30 +1088,18 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
|
||||
len = desc_len(sh_desc);
|
||||
init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
|
||||
|
||||
if (iv_contig) {
|
||||
src_dma = edesc->iv_dma;
|
||||
in_options = 0;
|
||||
} else {
|
||||
src_dma = edesc->sec4_sg_dma;
|
||||
sec4_sg_index += edesc->src_nents + 1;
|
||||
in_options = LDST_SGF;
|
||||
}
|
||||
append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options);
|
||||
append_seq_in_ptr(desc, edesc->sec4_sg_dma, req->nbytes + ivsize,
|
||||
LDST_SGF);
|
||||
|
||||
if (likely(req->src == req->dst)) {
|
||||
if (edesc->src_nents == 1 && iv_contig) {
|
||||
dst_dma = sg_dma_address(req->src);
|
||||
} else {
|
||||
dst_dma = edesc->sec4_sg_dma +
|
||||
sizeof(struct sec4_sg_entry);
|
||||
out_options = LDST_SGF;
|
||||
}
|
||||
dst_dma = edesc->sec4_sg_dma + sizeof(struct sec4_sg_entry);
|
||||
out_options = LDST_SGF;
|
||||
} else {
|
||||
if (edesc->dst_nents == 1) {
|
||||
dst_dma = sg_dma_address(req->dst);
|
||||
} else {
|
||||
dst_dma = edesc->sec4_sg_dma +
|
||||
sec4_sg_index * sizeof(struct sec4_sg_entry);
|
||||
dst_dma = edesc->sec4_sg_dma + (edesc->src_nents + 1) *
|
||||
sizeof(struct sec4_sg_entry);
|
||||
out_options = LDST_SGF;
|
||||
}
|
||||
}
|
||||
@@ -1116,13 +1111,12 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
|
||||
*/
|
||||
static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr,
|
||||
struct ablkcipher_edesc *edesc,
|
||||
struct ablkcipher_request *req,
|
||||
bool iv_contig)
|
||||
struct ablkcipher_request *req)
|
||||
{
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
u32 *desc = edesc->hw_desc;
|
||||
u32 out_options, in_options;
|
||||
u32 in_options;
|
||||
dma_addr_t dst_dma, src_dma;
|
||||
int len, sec4_sg_index = 0;
|
||||
|
||||
@@ -1148,15 +1142,9 @@ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr,
|
||||
}
|
||||
append_seq_in_ptr(desc, src_dma, req->nbytes, in_options);
|
||||
|
||||
if (iv_contig) {
|
||||
dst_dma = edesc->iv_dma;
|
||||
out_options = 0;
|
||||
} else {
|
||||
dst_dma = edesc->sec4_sg_dma +
|
||||
sec4_sg_index * sizeof(struct sec4_sg_entry);
|
||||
out_options = LDST_SGF;
|
||||
}
|
||||
append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, out_options);
|
||||
dst_dma = edesc->sec4_sg_dma + sec4_sg_index *
|
||||
sizeof(struct sec4_sg_entry);
|
||||
append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, LDST_SGF);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1245,7 +1233,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
GFP_DMA | flags);
|
||||
if (!edesc) {
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0);
|
||||
0, DMA_NONE, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@@ -1449,8 +1437,7 @@ static int aead_decrypt(struct aead_request *req)
|
||||
* allocate and map the ablkcipher extended descriptor for ablkcipher
|
||||
*/
|
||||
static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
*req, int desc_bytes,
|
||||
bool *iv_contig_out)
|
||||
*req, int desc_bytes)
|
||||
{
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||
@@ -1459,8 +1446,8 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
GFP_KERNEL : GFP_ATOMIC;
|
||||
int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0;
|
||||
struct ablkcipher_edesc *edesc;
|
||||
dma_addr_t iv_dma = 0;
|
||||
bool in_contig;
|
||||
dma_addr_t iv_dma;
|
||||
u8 *iv;
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes;
|
||||
|
||||
@@ -1504,33 +1491,20 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
}
|
||||
}
|
||||
|
||||
iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, iv_dma)) {
|
||||
dev_err(jrdev, "unable to map IV\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (mapped_src_nents == 1 &&
|
||||
iv_dma + ivsize == sg_dma_address(req->src)) {
|
||||
in_contig = true;
|
||||
sec4_sg_ents = 0;
|
||||
} else {
|
||||
in_contig = false;
|
||||
sec4_sg_ents = 1 + mapped_src_nents;
|
||||
}
|
||||
sec4_sg_ents = 1 + mapped_src_nents;
|
||||
dst_sg_idx = sec4_sg_ents;
|
||||
sec4_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0;
|
||||
sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry);
|
||||
|
||||
/* allocate space for base edesc and hw desc commands, link tables */
|
||||
edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes,
|
||||
/*
|
||||
* allocate space for base edesc and hw desc commands, link tables, IV
|
||||
*/
|
||||
edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes + ivsize,
|
||||
GFP_DMA | flags);
|
||||
if (!edesc) {
|
||||
dev_err(jrdev, "could not allocate extended descriptor\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, 0, 0);
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, DMA_NONE, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@@ -1539,13 +1513,24 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
edesc->sec4_sg_bytes = sec4_sg_bytes;
|
||||
edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
|
||||
desc_bytes;
|
||||
edesc->iv_dir = DMA_TO_DEVICE;
|
||||
|
||||
if (!in_contig) {
|
||||
dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
|
||||
sg_to_sec4_sg_last(req->src, mapped_src_nents,
|
||||
edesc->sec4_sg + 1, 0);
|
||||
/* Make sure IV is located in a DMAable area */
|
||||
iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes;
|
||||
memcpy(iv, req->info, ivsize);
|
||||
|
||||
iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, iv_dma)) {
|
||||
dev_err(jrdev, "unable to map IV\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, DMA_NONE, 0, 0);
|
||||
kfree(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
|
||||
sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg + 1, 0);
|
||||
|
||||
if (mapped_dst_nents > 1) {
|
||||
sg_to_sec4_sg_last(req->dst, mapped_dst_nents,
|
||||
edesc->sec4_sg + dst_sg_idx, 0);
|
||||
@@ -1556,7 +1541,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
|
||||
dev_err(jrdev, "unable to map S/G table\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, 0, 0);
|
||||
iv_dma, ivsize, DMA_TO_DEVICE, 0, 0);
|
||||
kfree(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
@@ -1569,7 +1554,6 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
sec4_sg_bytes, 1);
|
||||
#endif
|
||||
|
||||
*iv_contig_out = in_contig;
|
||||
return edesc;
|
||||
}
|
||||
|
||||
@@ -1579,19 +1563,16 @@ static int ablkcipher_encrypt(struct ablkcipher_request *req)
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||
struct device *jrdev = ctx->jrdev;
|
||||
bool iv_contig;
|
||||
u32 *desc;
|
||||
int ret = 0;
|
||||
|
||||
/* allocate extended descriptor */
|
||||
edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
|
||||
CAAM_CMD_SZ, &iv_contig);
|
||||
edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ);
|
||||
if (IS_ERR(edesc))
|
||||
return PTR_ERR(edesc);
|
||||
|
||||
/* Create and submit job descriptor*/
|
||||
init_ablkcipher_job(ctx->sh_desc_enc,
|
||||
ctx->sh_desc_enc_dma, edesc, req, iv_contig);
|
||||
init_ablkcipher_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req);
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
|
||||
@@ -1615,20 +1596,25 @@ static int ablkcipher_decrypt(struct ablkcipher_request *req)
|
||||
struct ablkcipher_edesc *edesc;
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
struct device *jrdev = ctx->jrdev;
|
||||
bool iv_contig;
|
||||
u32 *desc;
|
||||
int ret = 0;
|
||||
|
||||
/* allocate extended descriptor */
|
||||
edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
|
||||
CAAM_CMD_SZ, &iv_contig);
|
||||
edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ);
|
||||
if (IS_ERR(edesc))
|
||||
return PTR_ERR(edesc);
|
||||
|
||||
/*
|
||||
* The crypto API expects us to set the IV (req->info) to the last
|
||||
* ciphertext block.
|
||||
*/
|
||||
scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize,
|
||||
ivsize, 0);
|
||||
|
||||
/* Create and submit job descriptor*/
|
||||
init_ablkcipher_job(ctx->sh_desc_dec,
|
||||
ctx->sh_desc_dec_dma, edesc, req, iv_contig);
|
||||
init_ablkcipher_job(ctx->sh_desc_dec, ctx->sh_desc_dec_dma, edesc, req);
|
||||
desc = edesc->hw_desc;
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ",
|
||||
@@ -1653,8 +1639,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *req)
|
||||
*/
|
||||
static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
struct skcipher_givcrypt_request *greq,
|
||||
int desc_bytes,
|
||||
bool *iv_contig_out)
|
||||
int desc_bytes)
|
||||
{
|
||||
struct ablkcipher_request *req = &greq->creq;
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
@@ -1664,8 +1649,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
GFP_KERNEL : GFP_ATOMIC;
|
||||
int src_nents, mapped_src_nents, dst_nents, mapped_dst_nents;
|
||||
struct ablkcipher_edesc *edesc;
|
||||
dma_addr_t iv_dma = 0;
|
||||
bool out_contig;
|
||||
dma_addr_t iv_dma;
|
||||
u8 *iv;
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes;
|
||||
|
||||
@@ -1710,36 +1695,20 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if iv can be contiguous with source and destination.
|
||||
* If so, include it. If not, create scatterlist.
|
||||
*/
|
||||
iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, iv_dma)) {
|
||||
dev_err(jrdev, "unable to map IV\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
sec4_sg_ents = mapped_src_nents > 1 ? mapped_src_nents : 0;
|
||||
dst_sg_idx = sec4_sg_ents;
|
||||
if (mapped_dst_nents == 1 &&
|
||||
iv_dma + ivsize == sg_dma_address(req->dst)) {
|
||||
out_contig = true;
|
||||
} else {
|
||||
out_contig = false;
|
||||
sec4_sg_ents += 1 + mapped_dst_nents;
|
||||
}
|
||||
sec4_sg_ents += 1 + mapped_dst_nents;
|
||||
|
||||
/* allocate space for base edesc and hw desc commands, link tables */
|
||||
/*
|
||||
* allocate space for base edesc and hw desc commands, link tables, IV
|
||||
*/
|
||||
sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry);
|
||||
edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes,
|
||||
edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes + ivsize,
|
||||
GFP_DMA | flags);
|
||||
if (!edesc) {
|
||||
dev_err(jrdev, "could not allocate extended descriptor\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, 0, 0);
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, DMA_NONE, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@@ -1748,24 +1717,33 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
edesc->sec4_sg_bytes = sec4_sg_bytes;
|
||||
edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
|
||||
desc_bytes;
|
||||
edesc->iv_dir = DMA_FROM_DEVICE;
|
||||
|
||||
/* Make sure IV is located in a DMAable area */
|
||||
iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes;
|
||||
iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(jrdev, iv_dma)) {
|
||||
dev_err(jrdev, "unable to map IV\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, DMA_NONE, 0, 0);
|
||||
kfree(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (mapped_src_nents > 1)
|
||||
sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg,
|
||||
0);
|
||||
|
||||
if (!out_contig) {
|
||||
dma_to_sec4_sg_one(edesc->sec4_sg + dst_sg_idx,
|
||||
iv_dma, ivsize, 0);
|
||||
sg_to_sec4_sg_last(req->dst, mapped_dst_nents,
|
||||
edesc->sec4_sg + dst_sg_idx + 1, 0);
|
||||
}
|
||||
dma_to_sec4_sg_one(edesc->sec4_sg + dst_sg_idx, iv_dma, ivsize, 0);
|
||||
sg_to_sec4_sg_last(req->dst, mapped_dst_nents, edesc->sec4_sg +
|
||||
dst_sg_idx + 1, 0);
|
||||
|
||||
edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
|
||||
sec4_sg_bytes, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
|
||||
dev_err(jrdev, "unable to map S/G table\n");
|
||||
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, 0, 0);
|
||||
iv_dma, ivsize, DMA_FROM_DEVICE, 0, 0);
|
||||
kfree(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
@@ -1778,7 +1756,6 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
sec4_sg_bytes, 1);
|
||||
#endif
|
||||
|
||||
*iv_contig_out = out_contig;
|
||||
return edesc;
|
||||
}
|
||||
|
||||
@@ -1789,19 +1766,17 @@ static int ablkcipher_givencrypt(struct skcipher_givcrypt_request *creq)
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||
struct device *jrdev = ctx->jrdev;
|
||||
bool iv_contig = false;
|
||||
u32 *desc;
|
||||
int ret = 0;
|
||||
|
||||
/* allocate extended descriptor */
|
||||
edesc = ablkcipher_giv_edesc_alloc(creq, DESC_JOB_IO_LEN *
|
||||
CAAM_CMD_SZ, &iv_contig);
|
||||
edesc = ablkcipher_giv_edesc_alloc(creq, DESC_JOB_IO_LEN * CAAM_CMD_SZ);
|
||||
if (IS_ERR(edesc))
|
||||
return PTR_ERR(edesc);
|
||||
|
||||
/* Create and submit job descriptor*/
|
||||
init_ablkcipher_giv_job(ctx->sh_desc_givenc, ctx->sh_desc_givenc_dma,
|
||||
edesc, req, iv_contig);
|
||||
edesc, req);
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR,
|
||||
"ablkcipher jobdesc@" __stringify(__LINE__) ": ",
|
||||
|
||||
@@ -401,7 +401,7 @@ badkey:
|
||||
* @assoclen: associated data length, in CAAM endianness
|
||||
* @assoclen_dma: bus physical mapped address of req->assoclen
|
||||
* @drv_req: driver-specific request structure
|
||||
* @sgt: the h/w link table
|
||||
* @sgt: the h/w link table, followed by IV
|
||||
*/
|
||||
struct aead_edesc {
|
||||
int src_nents;
|
||||
@@ -412,9 +412,6 @@ struct aead_edesc {
|
||||
unsigned int assoclen;
|
||||
dma_addr_t assoclen_dma;
|
||||
struct caam_drv_req drv_req;
|
||||
#define CAAM_QI_MAX_AEAD_SG \
|
||||
((CAAM_QI_MEMCACHE_SIZE - offsetof(struct aead_edesc, sgt)) / \
|
||||
sizeof(struct qm_sg_entry))
|
||||
struct qm_sg_entry sgt[0];
|
||||
};
|
||||
|
||||
@@ -426,7 +423,7 @@ struct aead_edesc {
|
||||
* @qm_sg_bytes: length of dma mapped h/w link table
|
||||
* @qm_sg_dma: bus physical mapped address of h/w link table
|
||||
* @drv_req: driver-specific request structure
|
||||
* @sgt: the h/w link table
|
||||
* @sgt: the h/w link table, followed by IV
|
||||
*/
|
||||
struct ablkcipher_edesc {
|
||||
int src_nents;
|
||||
@@ -435,9 +432,6 @@ struct ablkcipher_edesc {
|
||||
int qm_sg_bytes;
|
||||
dma_addr_t qm_sg_dma;
|
||||
struct caam_drv_req drv_req;
|
||||
#define CAAM_QI_MAX_ABLKCIPHER_SG \
|
||||
((CAAM_QI_MEMCACHE_SIZE - offsetof(struct ablkcipher_edesc, sgt)) / \
|
||||
sizeof(struct qm_sg_entry))
|
||||
struct qm_sg_entry sgt[0];
|
||||
};
|
||||
|
||||
@@ -649,17 +643,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
}
|
||||
}
|
||||
|
||||
if ((alg->caam.rfc3686 && encrypt) || !alg->caam.geniv) {
|
||||
if ((alg->caam.rfc3686 && encrypt) || !alg->caam.geniv)
|
||||
ivsize = crypto_aead_ivsize(aead);
|
||||
iv_dma = dma_map_single(qidev, req->iv, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents,
|
||||
dst_nents, 0, 0, op_type, 0, 0);
|
||||
qi_cache_free(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create S/G table: req->assoclen, [IV,] req->src [, req->dst].
|
||||
@@ -667,16 +652,33 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||
*/
|
||||
qm_sg_ents = 1 + !!ivsize + mapped_src_nents +
|
||||
(mapped_dst_nents > 1 ? mapped_dst_nents : 0);
|
||||
if (unlikely(qm_sg_ents > CAAM_QI_MAX_AEAD_SG)) {
|
||||
dev_err(qidev, "Insufficient S/G entries: %d > %zu\n",
|
||||
qm_sg_ents, CAAM_QI_MAX_AEAD_SG);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, op_type, 0, 0);
|
||||
sg_table = &edesc->sgt[0];
|
||||
qm_sg_bytes = qm_sg_ents * sizeof(*sg_table);
|
||||
if (unlikely(offsetof(struct aead_edesc, sgt) + qm_sg_bytes + ivsize >
|
||||
CAAM_QI_MEMCACHE_SIZE)) {
|
||||
dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n",
|
||||
qm_sg_ents, ivsize);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
qi_cache_free(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
sg_table = &edesc->sgt[0];
|
||||
qm_sg_bytes = qm_sg_ents * sizeof(*sg_table);
|
||||
|
||||
if (ivsize) {
|
||||
u8 *iv = (u8 *)(sg_table + qm_sg_ents);
|
||||
|
||||
/* Make sure IV is located in a DMAable area */
|
||||
memcpy(iv, req->iv, ivsize);
|
||||
|
||||
iv_dma = dma_map_single(qidev, iv, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents,
|
||||
dst_nents, 0, 0, 0, 0, 0);
|
||||
qi_cache_free(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
edesc->src_nents = src_nents;
|
||||
edesc->dst_nents = dst_nents;
|
||||
@@ -813,15 +815,27 @@ static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status)
|
||||
#endif
|
||||
|
||||
ablkcipher_unmap(qidev, edesc, req);
|
||||
qi_cache_free(edesc);
|
||||
|
||||
/* In case initial IV was generated, copy it in GIVCIPHER request */
|
||||
if (edesc->drv_req.drv_ctx->op_type == GIVENCRYPT) {
|
||||
u8 *iv;
|
||||
struct skcipher_givcrypt_request *greq;
|
||||
|
||||
greq = container_of(req, struct skcipher_givcrypt_request,
|
||||
creq);
|
||||
iv = (u8 *)edesc->sgt + edesc->qm_sg_bytes;
|
||||
memcpy(greq->giv, iv, ivsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* The crypto API expects us to set the IV (req->info) to the last
|
||||
* ciphertext block. This is used e.g. by the CTS mode.
|
||||
*/
|
||||
scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
|
||||
ivsize, 0);
|
||||
if (edesc->drv_req.drv_ctx->op_type != DECRYPT)
|
||||
scatterwalk_map_and_copy(req->info, req->dst, req->nbytes -
|
||||
ivsize, ivsize, 0);
|
||||
|
||||
qi_cache_free(edesc);
|
||||
ablkcipher_request_complete(req, status);
|
||||
}
|
||||
|
||||
@@ -836,9 +850,9 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0;
|
||||
struct ablkcipher_edesc *edesc;
|
||||
dma_addr_t iv_dma;
|
||||
bool in_contig;
|
||||
u8 *iv;
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
int dst_sg_idx, qm_sg_ents;
|
||||
int dst_sg_idx, qm_sg_ents, qm_sg_bytes;
|
||||
struct qm_sg_entry *sg_table, *fd_sgt;
|
||||
struct caam_drv_ctx *drv_ctx;
|
||||
enum optype op_type = encrypt ? ENCRYPT : DECRYPT;
|
||||
@@ -885,55 +899,53 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
}
|
||||
}
|
||||
|
||||
iv_dma = dma_map_single(qidev, req->info, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
qm_sg_ents = 1 + mapped_src_nents;
|
||||
dst_sg_idx = qm_sg_ents;
|
||||
|
||||
qm_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0;
|
||||
qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry);
|
||||
if (unlikely(offsetof(struct ablkcipher_edesc, sgt) + qm_sg_bytes +
|
||||
ivsize > CAAM_QI_MEMCACHE_SIZE)) {
|
||||
dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n",
|
||||
qm_sg_ents, ivsize);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (mapped_src_nents == 1 &&
|
||||
iv_dma + ivsize == sg_dma_address(req->src)) {
|
||||
in_contig = true;
|
||||
qm_sg_ents = 0;
|
||||
} else {
|
||||
in_contig = false;
|
||||
qm_sg_ents = 1 + mapped_src_nents;
|
||||
}
|
||||
dst_sg_idx = qm_sg_ents;
|
||||
|
||||
qm_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0;
|
||||
if (unlikely(qm_sg_ents > CAAM_QI_MAX_ABLKCIPHER_SG)) {
|
||||
dev_err(qidev, "Insufficient S/G entries: %d > %zu\n",
|
||||
qm_sg_ents, CAAM_QI_MAX_ABLKCIPHER_SG);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, op_type, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* allocate space for base edesc and link tables */
|
||||
/* allocate space for base edesc, link tables and IV */
|
||||
edesc = qi_cache_alloc(GFP_DMA | flags);
|
||||
if (unlikely(!edesc)) {
|
||||
dev_err(qidev, "could not allocate extended descriptor\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, op_type, 0, 0);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* Make sure IV is located in a DMAable area */
|
||||
sg_table = &edesc->sgt[0];
|
||||
iv = (u8 *)(sg_table + qm_sg_ents);
|
||||
memcpy(iv, req->info, ivsize);
|
||||
|
||||
iv_dma = dma_map_single(qidev, iv, ivsize, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
qi_cache_free(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
edesc->src_nents = src_nents;
|
||||
edesc->dst_nents = dst_nents;
|
||||
edesc->iv_dma = iv_dma;
|
||||
sg_table = &edesc->sgt[0];
|
||||
edesc->qm_sg_bytes = qm_sg_ents * sizeof(*sg_table);
|
||||
edesc->qm_sg_bytes = qm_sg_bytes;
|
||||
edesc->drv_req.app_ctx = req;
|
||||
edesc->drv_req.cbk = ablkcipher_done;
|
||||
edesc->drv_req.drv_ctx = drv_ctx;
|
||||
|
||||
if (!in_contig) {
|
||||
dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0);
|
||||
sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + 1, 0);
|
||||
}
|
||||
dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0);
|
||||
sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + 1, 0);
|
||||
|
||||
if (mapped_dst_nents > 1)
|
||||
sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table +
|
||||
@@ -951,20 +963,12 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
|
||||
|
||||
fd_sgt = &edesc->drv_req.fd_sgt[0];
|
||||
|
||||
if (!in_contig)
|
||||
dma_to_qm_sg_one_last_ext(&fd_sgt[1], edesc->qm_sg_dma,
|
||||
ivsize + req->nbytes, 0);
|
||||
else
|
||||
dma_to_qm_sg_one_last(&fd_sgt[1], iv_dma, ivsize + req->nbytes,
|
||||
0);
|
||||
dma_to_qm_sg_one_last_ext(&fd_sgt[1], edesc->qm_sg_dma,
|
||||
ivsize + req->nbytes, 0);
|
||||
|
||||
if (req->src == req->dst) {
|
||||
if (!in_contig)
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma +
|
||||
sizeof(*sg_table), req->nbytes, 0);
|
||||
else
|
||||
dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(req->src),
|
||||
req->nbytes, 0);
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma +
|
||||
sizeof(*sg_table), req->nbytes, 0);
|
||||
} else if (mapped_dst_nents > 1) {
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx *
|
||||
sizeof(*sg_table), req->nbytes, 0);
|
||||
@@ -988,10 +992,10 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
int src_nents, mapped_src_nents, dst_nents, mapped_dst_nents;
|
||||
struct ablkcipher_edesc *edesc;
|
||||
dma_addr_t iv_dma;
|
||||
bool out_contig;
|
||||
u8 *iv;
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
struct qm_sg_entry *sg_table, *fd_sgt;
|
||||
int dst_sg_idx, qm_sg_ents;
|
||||
int dst_sg_idx, qm_sg_ents, qm_sg_bytes;
|
||||
struct caam_drv_ctx *drv_ctx;
|
||||
|
||||
drv_ctx = get_drv_ctx(ctx, GIVENCRYPT);
|
||||
@@ -1039,46 +1043,45 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
mapped_dst_nents = src_nents;
|
||||
}
|
||||
|
||||
iv_dma = dma_map_single(qidev, creq->giv, ivsize, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
qm_sg_ents = mapped_src_nents > 1 ? mapped_src_nents : 0;
|
||||
dst_sg_idx = qm_sg_ents;
|
||||
|
||||
qm_sg_ents += 1 + mapped_dst_nents;
|
||||
qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry);
|
||||
if (unlikely(offsetof(struct ablkcipher_edesc, sgt) + qm_sg_bytes +
|
||||
ivsize > CAAM_QI_MEMCACHE_SIZE)) {
|
||||
dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n",
|
||||
qm_sg_ents, ivsize);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
qm_sg_ents = mapped_src_nents > 1 ? mapped_src_nents : 0;
|
||||
dst_sg_idx = qm_sg_ents;
|
||||
if (mapped_dst_nents == 1 &&
|
||||
iv_dma + ivsize == sg_dma_address(req->dst)) {
|
||||
out_contig = true;
|
||||
} else {
|
||||
out_contig = false;
|
||||
qm_sg_ents += 1 + mapped_dst_nents;
|
||||
}
|
||||
|
||||
if (unlikely(qm_sg_ents > CAAM_QI_MAX_ABLKCIPHER_SG)) {
|
||||
dev_err(qidev, "Insufficient S/G entries: %d > %zu\n",
|
||||
qm_sg_ents, CAAM_QI_MAX_ABLKCIPHER_SG);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, GIVENCRYPT, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* allocate space for base edesc and link tables */
|
||||
/* allocate space for base edesc, link tables and IV */
|
||||
edesc = qi_cache_alloc(GFP_DMA | flags);
|
||||
if (!edesc) {
|
||||
dev_err(qidev, "could not allocate extended descriptor\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents,
|
||||
iv_dma, ivsize, GIVENCRYPT, 0, 0);
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* Make sure IV is located in a DMAable area */
|
||||
sg_table = &edesc->sgt[0];
|
||||
iv = (u8 *)(sg_table + qm_sg_ents);
|
||||
iv_dma = dma_map_single(qidev, iv, ivsize, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(qidev, iv_dma)) {
|
||||
dev_err(qidev, "unable to map IV\n");
|
||||
caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0,
|
||||
0, 0, 0, 0);
|
||||
qi_cache_free(edesc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
edesc->src_nents = src_nents;
|
||||
edesc->dst_nents = dst_nents;
|
||||
edesc->iv_dma = iv_dma;
|
||||
sg_table = &edesc->sgt[0];
|
||||
edesc->qm_sg_bytes = qm_sg_ents * sizeof(*sg_table);
|
||||
edesc->qm_sg_bytes = qm_sg_bytes;
|
||||
edesc->drv_req.app_ctx = req;
|
||||
edesc->drv_req.cbk = ablkcipher_done;
|
||||
edesc->drv_req.drv_ctx = drv_ctx;
|
||||
@@ -1086,11 +1089,9 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
if (mapped_src_nents > 1)
|
||||
sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table, 0);
|
||||
|
||||
if (!out_contig) {
|
||||
dma_to_qm_sg_one(sg_table + dst_sg_idx, iv_dma, ivsize, 0);
|
||||
sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table +
|
||||
dst_sg_idx + 1, 0);
|
||||
}
|
||||
dma_to_qm_sg_one(sg_table + dst_sg_idx, iv_dma, ivsize, 0);
|
||||
sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + dst_sg_idx + 1,
|
||||
0);
|
||||
|
||||
edesc->qm_sg_dma = dma_map_single(qidev, sg_table, edesc->qm_sg_bytes,
|
||||
DMA_TO_DEVICE);
|
||||
@@ -1111,13 +1112,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
|
||||
dma_to_qm_sg_one(&fd_sgt[1], sg_dma_address(req->src),
|
||||
req->nbytes, 0);
|
||||
|
||||
if (!out_contig)
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx *
|
||||
sizeof(*sg_table), ivsize + req->nbytes,
|
||||
0);
|
||||
else
|
||||
dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(req->dst),
|
||||
ivsize + req->nbytes, 0);
|
||||
dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx *
|
||||
sizeof(*sg_table), ivsize + req->nbytes, 0);
|
||||
|
||||
return edesc;
|
||||
}
|
||||
@@ -1127,6 +1123,7 @@ static inline int ablkcipher_crypt(struct ablkcipher_request *req, bool encrypt)
|
||||
struct ablkcipher_edesc *edesc;
|
||||
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
int ret;
|
||||
|
||||
if (unlikely(caam_congested))
|
||||
@@ -1137,6 +1134,14 @@ static inline int ablkcipher_crypt(struct ablkcipher_request *req, bool encrypt)
|
||||
if (IS_ERR(edesc))
|
||||
return PTR_ERR(edesc);
|
||||
|
||||
/*
|
||||
* The crypto API expects us to set the IV (req->info) to the last
|
||||
* ciphertext block.
|
||||
*/
|
||||
if (!encrypt)
|
||||
scatterwalk_map_and_copy(req->info, req->src, req->nbytes -
|
||||
ivsize, ivsize, 0);
|
||||
|
||||
ret = caam_qi_enqueue(ctx->qidev, &edesc->drv_req);
|
||||
if (!ret) {
|
||||
ret = -EINPROGRESS;
|
||||
|
||||
@@ -66,7 +66,7 @@ static void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc,
|
||||
struct caam_rsa_key *key = &ctx->key;
|
||||
struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
|
||||
size_t p_sz = key->p_sz;
|
||||
size_t q_sz = key->p_sz;
|
||||
size_t q_sz = key->q_sz;
|
||||
|
||||
dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
|
||||
@@ -83,7 +83,7 @@ static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc,
|
||||
struct caam_rsa_key *key = &ctx->key;
|
||||
struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
|
||||
size_t p_sz = key->p_sz;
|
||||
size_t q_sz = key->p_sz;
|
||||
size_t q_sz = key->q_sz;
|
||||
|
||||
dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
|
||||
@@ -166,18 +166,71 @@ static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err,
|
||||
akcipher_request_complete(req, err);
|
||||
}
|
||||
|
||||
static int caam_rsa_count_leading_zeros(struct scatterlist *sgl,
|
||||
unsigned int nbytes,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct sg_mapping_iter miter;
|
||||
int lzeros, ents;
|
||||
unsigned int len;
|
||||
unsigned int tbytes = nbytes;
|
||||
const u8 *buff;
|
||||
|
||||
ents = sg_nents_for_len(sgl, nbytes);
|
||||
if (ents < 0)
|
||||
return ents;
|
||||
|
||||
sg_miter_start(&miter, sgl, ents, SG_MITER_FROM_SG | flags);
|
||||
|
||||
lzeros = 0;
|
||||
len = 0;
|
||||
while (nbytes > 0) {
|
||||
while (len && !*buff) {
|
||||
lzeros++;
|
||||
len--;
|
||||
buff++;
|
||||
}
|
||||
|
||||
if (len && *buff)
|
||||
break;
|
||||
|
||||
sg_miter_next(&miter);
|
||||
buff = miter.addr;
|
||||
len = miter.length;
|
||||
|
||||
nbytes -= lzeros;
|
||||
lzeros = 0;
|
||||
}
|
||||
|
||||
miter.consumed = lzeros;
|
||||
sg_miter_stop(&miter);
|
||||
nbytes -= lzeros;
|
||||
|
||||
return tbytes - nbytes;
|
||||
}
|
||||
|
||||
static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
|
||||
size_t desclen)
|
||||
{
|
||||
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
|
||||
struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
|
||||
struct device *dev = ctx->dev;
|
||||
struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
|
||||
struct rsa_edesc *edesc;
|
||||
gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
|
||||
GFP_KERNEL : GFP_ATOMIC;
|
||||
int sg_flags = (flags == GFP_ATOMIC) ? SG_MITER_ATOMIC : 0;
|
||||
int sgc;
|
||||
int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
|
||||
int src_nents, dst_nents;
|
||||
int lzeros;
|
||||
|
||||
lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len, sg_flags);
|
||||
if (lzeros < 0)
|
||||
return ERR_PTR(lzeros);
|
||||
|
||||
req->src_len -= lzeros;
|
||||
req->src = scatterwalk_ffwd(req_ctx->src, req->src, lzeros);
|
||||
|
||||
src_nents = sg_nents_for_len(req->src, req->src_len);
|
||||
dst_nents = sg_nents_for_len(req->dst, req->dst_len);
|
||||
@@ -344,7 +397,7 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req,
|
||||
struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
|
||||
int sec4_sg_index = 0;
|
||||
size_t p_sz = key->p_sz;
|
||||
size_t q_sz = key->p_sz;
|
||||
size_t q_sz = key->q_sz;
|
||||
|
||||
pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, pdb->d_dma)) {
|
||||
@@ -419,7 +472,7 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req,
|
||||
struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
|
||||
int sec4_sg_index = 0;
|
||||
size_t p_sz = key->p_sz;
|
||||
size_t q_sz = key->p_sz;
|
||||
size_t q_sz = key->q_sz;
|
||||
|
||||
pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, pdb->p_dma)) {
|
||||
@@ -953,6 +1006,7 @@ static struct akcipher_alg caam_rsa = {
|
||||
.max_size = caam_rsa_max_size,
|
||||
.init = caam_rsa_init_tfm,
|
||||
.exit = caam_rsa_exit_tfm,
|
||||
.reqsize = sizeof(struct caam_rsa_req_ctx),
|
||||
.base = {
|
||||
.cra_name = "rsa",
|
||||
.cra_driver_name = "rsa-caam",
|
||||
|
||||
@@ -95,6 +95,14 @@ struct caam_rsa_ctx {
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
/**
|
||||
* caam_rsa_req_ctx - per request context.
|
||||
* @src: input scatterlist (stripped of leading zeros)
|
||||
*/
|
||||
struct caam_rsa_req_ctx {
|
||||
struct scatterlist src[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* rsa_edesc - s/w-extended rsa descriptor
|
||||
* @src_nents : number of segments in input scatterlist
|
||||
|
||||
@@ -46,8 +46,10 @@
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
@@ -149,6 +151,25 @@ struct zip_operation {
|
||||
u32 sizeofzops;
|
||||
};
|
||||
|
||||
static inline int zip_poll_result(union zip_zres_s *result)
|
||||
{
|
||||
int retries = 1000;
|
||||
|
||||
while (!result->s.compcode) {
|
||||
if (!--retries) {
|
||||
pr_err("ZIP ERR: request timed out");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(10);
|
||||
/*
|
||||
* Force re-reading of compcode which is updated
|
||||
* by the ZIP coprocessor.
|
||||
*/
|
||||
rmb();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error messages */
|
||||
#define zip_err(fmt, args...) pr_err("ZIP ERR:%s():%d: " \
|
||||
fmt "\n", __func__, __LINE__, ## args)
|
||||
|
||||
@@ -124,7 +124,7 @@ int zip_compress(const u8 *src, unsigned int slen,
|
||||
struct zip_kernel_ctx *zip_ctx)
|
||||
{
|
||||
struct zip_operation *zip_ops = NULL;
|
||||
struct zip_state zip_state;
|
||||
struct zip_state *zip_state;
|
||||
struct zip_device *zip = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -135,20 +135,23 @@ int zip_compress(const u8 *src, unsigned int slen,
|
||||
if (!zip)
|
||||
return -ENODEV;
|
||||
|
||||
memset(&zip_state, 0, sizeof(struct zip_state));
|
||||
zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
|
||||
if (!zip_state)
|
||||
return -ENOMEM;
|
||||
|
||||
zip_ops = &zip_ctx->zip_comp;
|
||||
|
||||
zip_ops->input_len = slen;
|
||||
zip_ops->output_len = *dlen;
|
||||
memcpy(zip_ops->input, src, slen);
|
||||
|
||||
ret = zip_deflate(zip_ops, &zip_state, zip);
|
||||
ret = zip_deflate(zip_ops, zip_state, zip);
|
||||
|
||||
if (!ret) {
|
||||
*dlen = zip_ops->output_len;
|
||||
memcpy(dst, zip_ops->output, *dlen);
|
||||
}
|
||||
|
||||
kfree(zip_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -157,7 +160,7 @@ int zip_decompress(const u8 *src, unsigned int slen,
|
||||
struct zip_kernel_ctx *zip_ctx)
|
||||
{
|
||||
struct zip_operation *zip_ops = NULL;
|
||||
struct zip_state zip_state;
|
||||
struct zip_state *zip_state;
|
||||
struct zip_device *zip = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -168,7 +171,10 @@ int zip_decompress(const u8 *src, unsigned int slen,
|
||||
if (!zip)
|
||||
return -ENODEV;
|
||||
|
||||
memset(&zip_state, 0, sizeof(struct zip_state));
|
||||
zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
|
||||
if (!zip_state)
|
||||
return -ENOMEM;
|
||||
|
||||
zip_ops = &zip_ctx->zip_decomp;
|
||||
memcpy(zip_ops->input, src, slen);
|
||||
|
||||
@@ -179,13 +185,13 @@ int zip_decompress(const u8 *src, unsigned int slen,
|
||||
zip_ops->input_len = slen;
|
||||
zip_ops->output_len = *dlen;
|
||||
|
||||
ret = zip_inflate(zip_ops, &zip_state, zip);
|
||||
ret = zip_inflate(zip_ops, zip_state, zip);
|
||||
|
||||
if (!ret) {
|
||||
*dlen = zip_ops->output_len;
|
||||
memcpy(dst, zip_ops->output, *dlen);
|
||||
}
|
||||
|
||||
kfree(zip_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,8 +129,8 @@ int zip_deflate(struct zip_operation *zip_ops, struct zip_state *s,
|
||||
/* Stats update for compression requests submitted */
|
||||
atomic64_inc(&zip_dev->stats.comp_req_submit);
|
||||
|
||||
while (!result_ptr->s.compcode)
|
||||
continue;
|
||||
/* Wait for completion or error */
|
||||
zip_poll_result(result_ptr);
|
||||
|
||||
/* Stats update for compression requests completed */
|
||||
atomic64_inc(&zip_dev->stats.comp_req_complete);
|
||||
|
||||
@@ -143,8 +143,8 @@ int zip_inflate(struct zip_operation *zip_ops, struct zip_state *s,
|
||||
/* Decompression requests submitted stats update */
|
||||
atomic64_inc(&zip_dev->stats.decomp_req_submit);
|
||||
|
||||
while (!result_ptr->s.compcode)
|
||||
continue;
|
||||
/* Wait for completion or error */
|
||||
zip_poll_result(result_ptr);
|
||||
|
||||
/* Decompression requests completed stats update */
|
||||
atomic64_inc(&zip_dev->stats.decomp_req_complete);
|
||||
|
||||
@@ -1082,7 +1082,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
|
||||
|
||||
if (test_bit(FLAGS_SGS_COPIED, &dd->flags))
|
||||
free_pages((unsigned long)sg_virt(ctx->sg),
|
||||
get_order(ctx->sg->length));
|
||||
get_order(ctx->sg->length + ctx->bufcnt));
|
||||
|
||||
if (test_bit(FLAGS_SGS_ALLOCED, &dd->flags))
|
||||
kfree(ctx->sg);
|
||||
|
||||
@@ -48,8 +48,6 @@ static int p8_aes_init(struct crypto_tfm *tfm)
|
||||
alg, PTR_ERR(fallback));
|
||||
return PTR_ERR(fallback);
|
||||
}
|
||||
printk(KERN_INFO "Using '%s' as fallback implementation.\n",
|
||||
crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback));
|
||||
|
||||
crypto_cipher_set_flags(fallback,
|
||||
crypto_cipher_get_flags((struct
|
||||
|
||||
@@ -52,9 +52,6 @@ static int p8_aes_cbc_init(struct crypto_tfm *tfm)
|
||||
alg, PTR_ERR(fallback));
|
||||
return PTR_ERR(fallback);
|
||||
}
|
||||
printk(KERN_INFO "Using '%s' as fallback implementation.\n",
|
||||
crypto_skcipher_driver_name(fallback));
|
||||
|
||||
|
||||
crypto_skcipher_set_flags(
|
||||
fallback,
|
||||
|
||||
@@ -48,8 +48,6 @@ static int p8_aes_ctr_init(struct crypto_tfm *tfm)
|
||||
alg, PTR_ERR(fallback));
|
||||
return PTR_ERR(fallback);
|
||||
}
|
||||
printk(KERN_INFO "Using '%s' as fallback implementation.\n",
|
||||
crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback));
|
||||
|
||||
crypto_blkcipher_set_flags(
|
||||
fallback,
|
||||
|
||||
@@ -53,8 +53,6 @@ static int p8_aes_xts_init(struct crypto_tfm *tfm)
|
||||
alg, PTR_ERR(fallback));
|
||||
return PTR_ERR(fallback);
|
||||
}
|
||||
printk(KERN_INFO "Using '%s' as fallback implementation.\n",
|
||||
crypto_skcipher_driver_name(fallback));
|
||||
|
||||
crypto_skcipher_set_flags(
|
||||
fallback,
|
||||
|
||||
@@ -64,8 +64,6 @@ static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
|
||||
alg, PTR_ERR(fallback));
|
||||
return PTR_ERR(fallback);
|
||||
}
|
||||
printk(KERN_INFO "Using '%s' as fallback implementation.\n",
|
||||
crypto_tfm_alg_driver_name(crypto_shash_tfm(fallback)));
|
||||
|
||||
crypto_shash_set_flags(fallback,
|
||||
crypto_shash_get_flags((struct crypto_shash
|
||||
|
||||
@@ -3313,6 +3313,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
||||
struct gpio_desc *desc = NULL;
|
||||
int status;
|
||||
enum gpio_lookup_flags lookupflags = 0;
|
||||
/* Maybe we have a device name, maybe not */
|
||||
const char *devname = dev ? dev_name(dev) : "?";
|
||||
|
||||
dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
|
||||
|
||||
@@ -3341,8 +3343,11 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
||||
return desc;
|
||||
}
|
||||
|
||||
/* If a connection label was passed use that, else use the device name as label */
|
||||
status = gpiod_request(desc, con_id ? con_id : dev_name(dev));
|
||||
/*
|
||||
* If a connection label was passed use that, else attempt to use
|
||||
* the device name as label
|
||||
*/
|
||||
status = gpiod_request(desc, con_id ? con_id : devname);
|
||||
if (status < 0)
|
||||
return ERR_PTR(status);
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ static const struct xpad_device {
|
||||
u8 mapping;
|
||||
u8 xtype;
|
||||
} xpad_device[] = {
|
||||
{ 0x0079, 0x18d4, "GPD Win 2 Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX },
|
||||
{ 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX },
|
||||
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
|
||||
@@ -411,6 +412,7 @@ static const signed short xpad_abs_triggers[] = {
|
||||
|
||||
static const struct usb_device_id xpad_table[] = {
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
|
||||
XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */
|
||||
XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
|
||||
|
||||
@@ -1260,6 +1260,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
|
||||
{ "ELAN060B", 0 },
|
||||
{ "ELAN060C", 0 },
|
||||
{ "ELAN0611", 0 },
|
||||
{ "ELAN0612", 0 },
|
||||
{ "ELAN1000", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -888,6 +888,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id goodix_acpi_match[] = {
|
||||
{ "GDIX1001", 0 },
|
||||
{ "GDIX1002", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
|
||||
|
||||
@@ -576,15 +576,9 @@ static void vmballoon_pop(struct vmballoon *b)
|
||||
}
|
||||
}
|
||||
|
||||
if (b->batch_page) {
|
||||
vunmap(b->batch_page);
|
||||
b->batch_page = NULL;
|
||||
}
|
||||
|
||||
if (b->page) {
|
||||
__free_page(b->page);
|
||||
b->page = NULL;
|
||||
}
|
||||
/* Clearing the batch_page unconditionally has no adverse effect */
|
||||
free_page((unsigned long)b->batch_page);
|
||||
b->batch_page = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -991,16 +985,13 @@ static const struct vmballoon_ops vmballoon_batched_ops = {
|
||||
|
||||
static bool vmballoon_init_batching(struct vmballoon *b)
|
||||
{
|
||||
b->page = alloc_page(VMW_PAGE_ALLOC_NOSLEEP);
|
||||
if (!b->page)
|
||||
struct page *page;
|
||||
|
||||
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (!page)
|
||||
return false;
|
||||
|
||||
b->batch_page = vmap(&b->page, 1, VM_MAP, PAGE_KERNEL);
|
||||
if (!b->batch_page) {
|
||||
__free_page(b->page);
|
||||
return false;
|
||||
}
|
||||
|
||||
b->batch_page = page_address(page);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ struct pn533_usb_phy {
|
||||
struct urb *out_urb;
|
||||
struct urb *in_urb;
|
||||
|
||||
struct urb *ack_urb;
|
||||
u8 *ack_buffer;
|
||||
|
||||
struct pn533 *priv;
|
||||
};
|
||||
|
||||
@@ -150,13 +153,16 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
|
||||
struct pn533_usb_phy *phy = dev->phy;
|
||||
static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
|
||||
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
|
||||
int rc;
|
||||
|
||||
phy->out_urb->transfer_buffer = (u8 *)ack;
|
||||
phy->out_urb->transfer_buffer_length = sizeof(ack);
|
||||
rc = usb_submit_urb(phy->out_urb, flags);
|
||||
if (!phy->ack_buffer) {
|
||||
phy->ack_buffer = kmemdup(ack, sizeof(ack), flags);
|
||||
if (!phy->ack_buffer)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return rc;
|
||||
phy->ack_urb->transfer_buffer = phy->ack_buffer;
|
||||
phy->ack_urb->transfer_buffer_length = sizeof(ack);
|
||||
return usb_submit_urb(phy->ack_urb, flags);
|
||||
}
|
||||
|
||||
static int pn533_usb_send_frame(struct pn533 *dev,
|
||||
@@ -375,26 +381,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
|
||||
/* Power on th reader (CCID cmd) */
|
||||
u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON,
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 0};
|
||||
char *buffer;
|
||||
int transferred;
|
||||
int rc;
|
||||
void *cntx;
|
||||
struct pn533_acr122_poweron_rdr_arg arg;
|
||||
|
||||
dev_dbg(&phy->udev->dev, "%s\n", __func__);
|
||||
|
||||
buffer = kmemdup(cmd, sizeof(cmd), GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&arg.done);
|
||||
cntx = phy->in_urb->context; /* backup context */
|
||||
|
||||
phy->in_urb->complete = pn533_acr122_poweron_rdr_resp;
|
||||
phy->in_urb->context = &arg;
|
||||
|
||||
phy->out_urb->transfer_buffer = cmd;
|
||||
phy->out_urb->transfer_buffer_length = sizeof(cmd);
|
||||
|
||||
print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
cmd, sizeof(cmd), false);
|
||||
|
||||
rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
|
||||
if (rc) {
|
||||
rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd),
|
||||
&transferred, 0);
|
||||
kfree(buffer);
|
||||
if (rc || (transferred != sizeof(cmd))) {
|
||||
nfc_err(&phy->udev->dev,
|
||||
"Reader power on cmd error %d\n", rc);
|
||||
return rc;
|
||||
@@ -490,8 +501,9 @@ static int pn533_usb_probe(struct usb_interface *interface,
|
||||
|
||||
phy->in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
phy->out_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
phy->ack_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
|
||||
if (!phy->in_urb || !phy->out_urb)
|
||||
if (!phy->in_urb || !phy->out_urb || !phy->ack_urb)
|
||||
goto error;
|
||||
|
||||
usb_fill_bulk_urb(phy->in_urb, phy->udev,
|
||||
@@ -501,7 +513,9 @@ static int pn533_usb_probe(struct usb_interface *interface,
|
||||
usb_fill_bulk_urb(phy->out_urb, phy->udev,
|
||||
usb_sndbulkpipe(phy->udev, out_endpoint),
|
||||
NULL, 0, pn533_send_complete, phy);
|
||||
|
||||
usb_fill_bulk_urb(phy->ack_urb, phy->udev,
|
||||
usb_sndbulkpipe(phy->udev, out_endpoint),
|
||||
NULL, 0, pn533_send_complete, phy);
|
||||
|
||||
switch (id->driver_info) {
|
||||
case PN533_DEVICE_STD:
|
||||
@@ -554,6 +568,7 @@ static int pn533_usb_probe(struct usb_interface *interface,
|
||||
error:
|
||||
usb_free_urb(phy->in_urb);
|
||||
usb_free_urb(phy->out_urb);
|
||||
usb_free_urb(phy->ack_urb);
|
||||
usb_put_dev(phy->udev);
|
||||
kfree(in_buf);
|
||||
|
||||
@@ -573,10 +588,13 @@ static void pn533_usb_disconnect(struct usb_interface *interface)
|
||||
|
||||
usb_kill_urb(phy->in_urb);
|
||||
usb_kill_urb(phy->out_urb);
|
||||
usb_kill_urb(phy->ack_urb);
|
||||
|
||||
kfree(phy->in_urb->transfer_buffer);
|
||||
usb_free_urb(phy->in_urb);
|
||||
usb_free_urb(phy->out_urb);
|
||||
usb_free_urb(phy->ack_urb);
|
||||
kfree(phy->ack_buffer);
|
||||
|
||||
nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n");
|
||||
}
|
||||
|
||||
@@ -178,6 +178,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
|
||||
struct device *dev = &qphy->phy->dev;
|
||||
u8 *val;
|
||||
|
||||
/* efuse register is optional */
|
||||
if (!qphy->cell)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Read efuse register having TUNE2 parameter's high nibble.
|
||||
* If efuse register shows value as 0x0, or if we fail to find
|
||||
|
||||
@@ -131,8 +131,11 @@ err2:
|
||||
|
||||
void ion_buffer_destroy(struct ion_buffer *buffer)
|
||||
{
|
||||
if (WARN_ON(buffer->kmap_cnt > 0))
|
||||
if (buffer->kmap_cnt > 0) {
|
||||
pr_warn_once("%s: buffer still mapped in the kernel\n",
|
||||
__func__);
|
||||
buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
|
||||
}
|
||||
buffer->heap->ops->free(buffer);
|
||||
kfree(buffer);
|
||||
}
|
||||
|
||||
@@ -1100,13 +1100,14 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE;
|
||||
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
|
||||
static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
|
||||
|
||||
static const struct of_device_id omap8250_dt_ids[] = {
|
||||
{ .compatible = "ti,omap2-uart" },
|
||||
{ .compatible = "ti,omap3-uart" },
|
||||
{ .compatible = "ti,omap4-uart" },
|
||||
{ .compatible = "ti,omap4-uart", .data = &omap4_habit, },
|
||||
{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
|
||||
{ .compatible = "ti,am4372-uart", .data = &am3352_habit, },
|
||||
{ .compatible = "ti,dra742-uart", .data = &dra742_habit, },
|
||||
@@ -1343,6 +1344,19 @@ static int omap8250_soft_reset(struct device *dev)
|
||||
int sysc;
|
||||
int syss;
|
||||
|
||||
/*
|
||||
* At least on omap4, unused uarts may not idle after reset without
|
||||
* a basic scr dma configuration even with no dma in use. The
|
||||
* module clkctrl status bits will be 1 instead of 3 blocking idle
|
||||
* for the whole clockdomain. The softreset below will clear scr,
|
||||
* and we restore it on resume so this is safe to do on all SoCs
|
||||
* needing omap8250_soft_reset() quirk. Do it in two writes as
|
||||
* recommended in the comment for omap8250_update_scr().
|
||||
*/
|
||||
serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
|
||||
serial_out(up, UART_OMAP_SCR,
|
||||
OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL);
|
||||
|
||||
sysc = serial_in(up, UART_OMAP_SYSC);
|
||||
|
||||
/* softreset the UART */
|
||||
|
||||
@@ -1747,10 +1747,26 @@ static int pl011_allocate_irq(struct uart_amba_port *uap)
|
||||
*/
|
||||
static void pl011_enable_interrupts(struct uart_amba_port *uap)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
|
||||
/* Clear out any spuriously appearing RX interrupts */
|
||||
pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
|
||||
|
||||
/*
|
||||
* RXIS is asserted only when the RX FIFO transitions from below
|
||||
* to above the trigger threshold. If the RX FIFO is already
|
||||
* full to the threshold this can't happen and RXIS will now be
|
||||
* stuck off. Drain the RX FIFO explicitly to fix this:
|
||||
*/
|
||||
for (i = 0; i < uap->fifosize * 2; ++i) {
|
||||
if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE)
|
||||
break;
|
||||
|
||||
pl011_read(uap, REG_DR);
|
||||
}
|
||||
|
||||
uap->im = UART011_RTIM;
|
||||
if (!pl011_dma_rx_running(uap))
|
||||
uap->im |= UART011_RXIM;
|
||||
|
||||
@@ -1786,7 +1786,6 @@ static int atmel_startup(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
@@ -1801,8 +1800,8 @@ static int atmel_startup(struct uart_port *port)
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(port->irq, atmel_interrupt,
|
||||
IRQF_SHARED | IRQF_COND_SUSPEND,
|
||||
tty ? tty->name : "atmel_serial", port);
|
||||
IRQF_SHARED | IRQF_COND_SUSPEND,
|
||||
dev_name(&pdev->dev), port);
|
||||
if (retval) {
|
||||
dev_err(port->dev, "atmel_startup - Can't get irq\n");
|
||||
return retval;
|
||||
|
||||
@@ -865,15 +865,12 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
||||
dma->rx_conf.direction = DMA_DEV_TO_MEM;
|
||||
dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH;
|
||||
dma->rx_conf.src_maxburst = 16;
|
||||
dma->rx_conf.src_maxburst = 1;
|
||||
|
||||
dma->tx_conf.direction = DMA_MEM_TO_DEV;
|
||||
dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH;
|
||||
if (dma_get_cache_alignment() >= 16)
|
||||
dma->tx_conf.dst_maxburst = 16;
|
||||
else
|
||||
dma->tx_conf.dst_maxburst = 1;
|
||||
dma->tx_conf.dst_maxburst = 1;
|
||||
|
||||
dma->rx_chan = dma_request_chan(p->port.dev, "rx");
|
||||
|
||||
|
||||
@@ -2669,8 +2669,8 @@ found:
|
||||
dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i],
|
||||
PTR_ERR(clk));
|
||||
else
|
||||
dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i],
|
||||
clk, clk);
|
||||
dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i],
|
||||
clk, clk_get_rate(clk));
|
||||
sci_port->clks[i] = IS_ERR(clk) ? NULL : clk;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -635,19 +635,19 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
list_add(&req->list, &dev->tx_reqs_active);
|
||||
|
||||
/* here, we unlock, and only unlock, to avoid deadlock. */
|
||||
spin_unlock(&dev->lock);
|
||||
value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
|
||||
spin_lock(&dev->lock);
|
||||
if (value) {
|
||||
list_del(&req->list);
|
||||
list_add(&req->list, &dev->tx_reqs);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
mutex_unlock(&dev->lock_printer_io);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
list_add(&req->list, &dev->tx_reqs_active);
|
||||
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
@@ -623,6 +623,13 @@ static void usb3_disconnect(struct renesas_usb3 *usb3)
|
||||
usb3_usb2_pullup(usb3, 0);
|
||||
usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
|
||||
usb3_reset_epc(usb3);
|
||||
usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM | USB_INT_1_B3_PLLWKUP |
|
||||
USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE |
|
||||
USB_INT_1_SPEED | USB_INT_1_B3_WRMRST |
|
||||
USB_INT_1_B3_HOTRST | USB_INT_1_B2_SPND |
|
||||
USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST);
|
||||
usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
|
||||
usb3_init_epc_registers(usb3);
|
||||
|
||||
if (usb3->driver)
|
||||
usb3->driver->disconnect(&usb3->gadget);
|
||||
|
||||
@@ -836,6 +836,12 @@ static int uas_slave_configure(struct scsi_device *sdev)
|
||||
if (devinfo->flags & US_FL_BROKEN_FUA)
|
||||
sdev->broken_fua = 1;
|
||||
|
||||
/* UAS also needs to support FL_ALWAYS_SYNC */
|
||||
if (devinfo->flags & US_FL_ALWAYS_SYNC) {
|
||||
sdev->skip_ms_page_3f = 1;
|
||||
sdev->skip_ms_page_8 = 1;
|
||||
sdev->wce_default_on = 1;
|
||||
}
|
||||
scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2340,6 +2340,15 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
|
||||
"Micro Mini 1GB",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
|
||||
|
||||
/* "G-DRIVE" external HDD hangs on write without these.
|
||||
* Patch submitted by Alexander Kappner <agk@godking.net>
|
||||
*/
|
||||
UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999,
|
||||
"SimpleTech",
|
||||
"External HDD",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_ALWAYS_SYNC),
|
||||
|
||||
/*
|
||||
* Nick Bowler <nbowler@elliptictech.com>
|
||||
* SCSI stack spams (otherwise harmless) error messages.
|
||||
|
||||
@@ -183,3 +183,12 @@ UNUSUAL_DEV(0x4971, 0x8017, 0x0000, 0x9999,
|
||||
"External HDD",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_REPORT_OPCODES),
|
||||
|
||||
/* "G-DRIVE" external HDD hangs on write without these.
|
||||
* Patch submitted by Alexander Kappner <agk@godking.net>
|
||||
*/
|
||||
UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999,
|
||||
"SimpleTech",
|
||||
"External HDD",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_ALWAYS_SYNC),
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Hardening for Spectre-v1 */
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include "usbip_common.h"
|
||||
#include "vhci.h"
|
||||
|
||||
@@ -219,16 +222,20 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int valid_port(__u32 pdev_nr, __u32 rhport)
|
||||
static int valid_port(__u32 *pdev_nr, __u32 *rhport)
|
||||
{
|
||||
if (pdev_nr >= vhci_num_controllers) {
|
||||
pr_err("pdev %u\n", pdev_nr);
|
||||
if (*pdev_nr >= vhci_num_controllers) {
|
||||
pr_err("pdev %u\n", *pdev_nr);
|
||||
return 0;
|
||||
}
|
||||
if (rhport >= VHCI_HC_PORTS) {
|
||||
pr_err("rhport %u\n", rhport);
|
||||
*pdev_nr = array_index_nospec(*pdev_nr, vhci_num_controllers);
|
||||
|
||||
if (*rhport >= VHCI_HC_PORTS) {
|
||||
pr_err("rhport %u\n", *rhport);
|
||||
return 0;
|
||||
}
|
||||
*rhport = array_index_nospec(*rhport, VHCI_HC_PORTS);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -246,7 +253,7 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
|
||||
pdev_nr = port_to_pdev_nr(port);
|
||||
rhport = port_to_rhport(port);
|
||||
|
||||
if (!valid_port(pdev_nr, rhport))
|
||||
if (!valid_port(&pdev_nr, &rhport))
|
||||
return -EINVAL;
|
||||
|
||||
hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
|
||||
@@ -272,7 +279,8 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
|
||||
|
||||
static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed)
|
||||
static int valid_args(__u32 *pdev_nr, __u32 *rhport,
|
||||
enum usb_device_speed speed)
|
||||
{
|
||||
if (!valid_port(pdev_nr, rhport)) {
|
||||
return 0;
|
||||
@@ -336,7 +344,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
|
||||
sockfd, devid, speed);
|
||||
|
||||
/* check received parameters */
|
||||
if (!valid_args(pdev_nr, rhport, speed))
|
||||
if (!valid_args(&pdev_nr, &rhport, speed))
|
||||
return -EINVAL;
|
||||
|
||||
hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
|
||||
|
||||
@@ -437,6 +437,24 @@ static int verify_address_len(const void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sadb_key_len(const struct sadb_key *key)
|
||||
{
|
||||
int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8);
|
||||
|
||||
return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes,
|
||||
sizeof(uint64_t));
|
||||
}
|
||||
|
||||
static int verify_key_len(const void *p)
|
||||
{
|
||||
const struct sadb_key *key = p;
|
||||
|
||||
if (sadb_key_len(key) > key->sadb_key_len)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx)
|
||||
{
|
||||
return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
|
||||
@@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void *
|
||||
return -EINVAL;
|
||||
if (ext_hdrs[ext_type-1] != NULL)
|
||||
return -EINVAL;
|
||||
if (ext_type == SADB_EXT_ADDRESS_SRC ||
|
||||
ext_type == SADB_EXT_ADDRESS_DST ||
|
||||
ext_type == SADB_EXT_ADDRESS_PROXY ||
|
||||
ext_type == SADB_X_EXT_NAT_T_OA) {
|
||||
switch (ext_type) {
|
||||
case SADB_EXT_ADDRESS_SRC:
|
||||
case SADB_EXT_ADDRESS_DST:
|
||||
case SADB_EXT_ADDRESS_PROXY:
|
||||
case SADB_X_EXT_NAT_T_OA:
|
||||
if (verify_address_len(p))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ext_type == SADB_X_EXT_SEC_CTX) {
|
||||
break;
|
||||
case SADB_X_EXT_SEC_CTX:
|
||||
if (verify_sec_ctx_len(p))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case SADB_EXT_KEY_AUTH:
|
||||
case SADB_EXT_KEY_ENCRYPT:
|
||||
if (verify_key_len(p))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ext_hdrs[ext_type-1] = (void *) p;
|
||||
}
|
||||
@@ -1104,14 +1131,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
||||
key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
|
||||
if (key != NULL &&
|
||||
sa->sadb_sa_auth != SADB_X_AALG_NULL &&
|
||||
((key->sadb_key_bits+7) / 8 == 0 ||
|
||||
(key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
|
||||
key->sadb_key_bits == 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
|
||||
if (key != NULL &&
|
||||
sa->sadb_sa_encrypt != SADB_EALG_NULL &&
|
||||
((key->sadb_key_bits+7) / 8 == 0 ||
|
||||
(key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
|
||||
key->sadb_key_bits == 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
x = xfrm_state_alloc(net);
|
||||
|
||||
@@ -875,22 +875,26 @@ static int nft_ct_helper_obj_dump(struct sk_buff *skb,
|
||||
struct nft_object *obj, bool reset)
|
||||
{
|
||||
const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
const struct nf_conntrack_helper *helper = priv->helper4;
|
||||
const struct nf_conntrack_helper *helper;
|
||||
u16 family;
|
||||
|
||||
if (priv->helper4 && priv->helper6) {
|
||||
family = NFPROTO_INET;
|
||||
helper = priv->helper4;
|
||||
} else if (priv->helper6) {
|
||||
family = NFPROTO_IPV6;
|
||||
helper = priv->helper6;
|
||||
} else {
|
||||
family = NFPROTO_IPV4;
|
||||
helper = priv->helper4;
|
||||
}
|
||||
|
||||
if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name))
|
||||
return -1;
|
||||
|
||||
if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto))
|
||||
return -1;
|
||||
|
||||
if (priv->helper4 && priv->helper6)
|
||||
family = NFPROTO_INET;
|
||||
else if (priv->helper6)
|
||||
family = NFPROTO_IPV6;
|
||||
else
|
||||
family = NFPROTO_IPV4;
|
||||
|
||||
if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family)))
|
||||
return -1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user