static int ext4_ioc_getfsmap(struct super_block *sb, struct fsmap_head __user *arg) { struct getfsmap_info info = {0}; struct ext4_fsmap_head xhead = {0}; struct fsmap_head head; bool aborted = false; int error; if (copy_from_user(&head, arg, sizeof(struct fsmap_head))) return -EFAULT; if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) || memchr_inv(head.fmh_keys[0].fmr_reserved, 0, sizeof(head.fmh_keys[0].fmr_reserved)) || memchr_inv(head.fmh_keys[1].fmr_reserved, 0, sizeof(head.fmh_keys[1].fmr_reserved))) return -EINVAL; /* * ext4 doesn't report file extents at all, so the only valid * file offsets are the magic ones (all zeroes or all ones). */ if (head.fmh_keys[0].fmr_offset || (head.fmh_keys[1].fmr_offset != 0 && head.fmh_keys[1].fmr_offset != -1ULL)) return -EINVAL; xhead.fmh_iflags = head.fmh_iflags; xhead.fmh_count = head.fmh_count; ext4_fsmap_to_internal(sb, &xhead.fmh_keys[0], &head.fmh_keys[0]); ext4_fsmap_to_internal(sb, &xhead.fmh_keys[1], &head.fmh_keys[1]); trace_ext4_getfsmap_low_key(sb, &xhead.fmh_keys[0]); trace_ext4_getfsmap_high_key(sb, &xhead.fmh_keys[1]); info.gi_sb = sb; info.gi_data = arg; error = ext4_getfsmap(sb, &xhead, ext4_getfsmap_format, &info); if (error == EXT4_QUERY_RANGE_ABORT) { error = 0; aborted = true; } else if (error) return error; /* If we didn't abort, set the "last" flag in the last fmx */ if (!aborted && info.gi_idx) { info.gi_last_flags |= FMR_OF_LAST; if (copy_to_user(&info.gi_data->fmh_recs[info.gi_idx - 1].fmr_flags, &info.gi_last_flags, sizeof(info.gi_last_flags))) return -EFAULT; } /* copy back header */ head.fmh_entries = xhead.fmh_entries; head.fmh_oflags = xhead.fmh_oflags; if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) return -EFAULT; return 0; }
static int __printf(4, 0) __init do_test(int bufsize, const char *expect, int elen, const char *fmt, va_list ap) { va_list aq; int ret, written; total_tests++; memset(alloced_buffer, FILL_CHAR, BUF_SIZE + 2*PAD_SIZE); va_copy(aq, ap); ret = vsnprintf(test_buffer, bufsize, fmt, aq); va_end(aq); if (ret != elen) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) returned %d, expected %d\n", bufsize, fmt, ret, elen); return 1; } if (memchr_inv(alloced_buffer, FILL_CHAR, PAD_SIZE)) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n", bufsize, fmt); return 1; } if (!bufsize) { if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE + PAD_SIZE)) { pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n", fmt); return 1; } return 0; } written = min(bufsize-1, elen); if (test_buffer[written]) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not nul-terminate buffer\n", bufsize, fmt); return 1; } if (memchr_inv(test_buffer + written + 1, FILL_CHAR, BUF_SIZE + PAD_SIZE - (written + 1))) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n", bufsize, fmt); return 1; } if (memcmp(test_buffer, expect, written)) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n", bufsize, fmt, test_buffer, written, expect); return 1; } return 0; }
static void check_poison_mem(unsigned char *mem, size_t bytes) { static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); unsigned char *start; unsigned char *end; if (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY)) return; start = memchr_inv(mem, PAGE_POISON, bytes); if (!start) return; for (end = mem + bytes - 1; end > start; end--) { if (*end != PAGE_POISON) break; } if (!__ratelimit(&ratelimit)) return; else if (start == end && single_bit_flip(*start, PAGE_POISON)) pr_err("pagealloc: single bit error\n"); else pr_err("pagealloc: memory corruption\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, end - start + 1, 1); dump_stack(); }
//Baron adds to avoid FreeBSD warning int ieee80211_is_empty_essid(const char *essid, int essid_len) { /* Single white space is for Linksys APs */ if (essid_len == 1 && essid[0] == ' ') return 1; /* Otherwise, if the entire essid is 0, we assume it is hidden */ return !memchr_inv(essid, 0, essid_len); }
static int igt_dmabuf_export_vmap(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *ptr; int err; obj = i915_gem_object_create(i915, PAGE_SIZE); if (IS_ERR(obj)) return PTR_ERR(obj); dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); if (IS_ERR(dmabuf)) { pr_err("i915_gem_prime_export failed with err=%d\n", (int)PTR_ERR(dmabuf)); err = PTR_ERR(dmabuf); goto err_obj; } i915_gem_object_put(obj); ptr = dma_buf_vmap(dmabuf); if (IS_ERR(ptr)) { err = PTR_ERR(ptr); pr_err("dma_buf_vmap failed with err=%d\n", err); goto out; } if (memchr_inv(ptr, 0, dmabuf->size)) { pr_err("Exported object not initialiased to zero!\n"); err = -EINVAL; goto out; } memset(ptr, 0xc5, dmabuf->size); err = 0; dma_buf_vunmap(dmabuf, ptr); out: dma_buf_put(dmabuf); return err; err_obj: i915_gem_object_put(obj); return err; }
static void check_poison_mem(unsigned char *mem, size_t bytes) { static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); unsigned char *start; unsigned char *end; /* IAMROOT-12AB: * ------------- * 지정된 주소부터 bytes 만큼 c가 아닌 값이 있는지 찾아 그 주소를 반환한다. * 정상적으로 모든 값이 c가 있는 경우 함수를 빠져나간다. */ start = memchr_inv(mem, PAGE_POISON, bytes); if (!start) return; for (end = mem + bytes - 1; end > start; end--) { if (*end != PAGE_POISON) break; } /* IAMROOT-12AB: * ------------- * ratelimit(5초에 10번)을 초과하는 경우 함수를 빠져나간다. */ if (!__ratelimit(&ratelimit)) return; /* IAMROOT-12AB: * ------------- * 1비트만 다른 경우와 그 이상의 비트가 오류가 있는지에 따라 구분하여 출력한다. */ else if (start == end && single_bit_flip(*start, PAGE_POISON)) printk(KERN_ERR "pagealloc: single bit error\n"); else printk(KERN_ERR "pagealloc: memory corruption\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, end - start + 1, 1); dump_stack(); }
/* * Note: some of the ioctl's return positive numbers as a * byte count indicating success, such as readlink_by_handle. * So we don't "sign flip" like most other routines. This means * true errors need to be returned as a negative value. */ long xfs_file_ioctl( struct file *filp, unsigned int cmd, unsigned long p) { struct inode *inode = file_inode(filp); struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; void __user *arg = (void __user *)p; int ioflags = 0; int error; if (filp->f_mode & FMODE_NOCMTIME) ioflags |= IO_INVIS; trace_xfs_file_ioctl(ip); switch (cmd) { case FITRIM: return xfs_ioc_trim(mp, arg); case XFS_IOC_ALLOCSP: case XFS_IOC_FREESP: case XFS_IOC_RESVSP: case XFS_IOC_UNRESVSP: case XFS_IOC_ALLOCSP64: case XFS_IOC_FREESP64: case XFS_IOC_RESVSP64: case XFS_IOC_UNRESVSP64: case XFS_IOC_ZERO_RANGE: { xfs_flock64_t bf; if (copy_from_user(&bf, arg, sizeof(bf))) return -XFS_ERROR(EFAULT); return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); } case XFS_IOC_DIOINFO: { struct dioattr da; xfs_buftarg_t *target = XFS_IS_REALTIME_INODE(ip) ? mp->m_rtdev_targp : mp->m_ddev_targp; da.d_mem = da.d_miniosz = 1 << target->bt_sshift; da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); if (copy_to_user(arg, &da, sizeof(da))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_FSBULKSTAT_SINGLE: case XFS_IOC_FSBULKSTAT: case XFS_IOC_FSINUMBERS: return xfs_ioc_bulkstat(mp, cmd, arg); case XFS_IOC_FSGEOMETRY_V1: return xfs_ioc_fsgeometry_v1(mp, arg); case XFS_IOC_FSGEOMETRY: return xfs_ioc_fsgeometry(mp, arg); case XFS_IOC_GETVERSION: return put_user(inode->i_generation, (int __user *)arg); case XFS_IOC_FSGETXATTR: return xfs_ioc_fsgetxattr(ip, 0, arg); case XFS_IOC_FSGETXATTRA: return xfs_ioc_fsgetxattr(ip, 1, arg); case XFS_IOC_FSSETXATTR: return xfs_ioc_fssetxattr(ip, filp, arg); case XFS_IOC_GETXFLAGS: return xfs_ioc_getxflags(ip, arg); case XFS_IOC_SETXFLAGS: return xfs_ioc_setxflags(ip, filp, arg); case XFS_IOC_FSSETDM: { struct fsdmidata dmi; if (copy_from_user(&dmi, arg, sizeof(dmi))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, dmi.fsd_dmstate); mnt_drop_write_file(filp); return -error; } case XFS_IOC_GETBMAP: case XFS_IOC_GETBMAPA: return xfs_ioc_getbmap(ip, ioflags, cmd, arg); case XFS_IOC_GETBMAPX: return xfs_ioc_getbmapx(ip, arg); case XFS_IOC_FD_TO_HANDLE: case XFS_IOC_PATH_TO_HANDLE: case XFS_IOC_PATH_TO_FSHANDLE: { xfs_fsop_handlereq_t hreq; if (copy_from_user(&hreq, arg, sizeof(hreq))) return -XFS_ERROR(EFAULT); return xfs_find_handle(cmd, &hreq); } case XFS_IOC_OPEN_BY_HANDLE: { xfs_fsop_handlereq_t hreq; if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) return -XFS_ERROR(EFAULT); return xfs_open_by_handle(filp, &hreq); } case XFS_IOC_FSSETDM_BY_HANDLE: return xfs_fssetdm_by_handle(filp, arg); case XFS_IOC_READLINK_BY_HANDLE: { xfs_fsop_handlereq_t hreq; if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) return -XFS_ERROR(EFAULT); return xfs_readlink_by_handle(filp, &hreq); } case XFS_IOC_ATTRLIST_BY_HANDLE: return xfs_attrlist_by_handle(filp, arg); case XFS_IOC_ATTRMULTI_BY_HANDLE: return xfs_attrmulti_by_handle(filp, arg); case XFS_IOC_SWAPEXT: { struct xfs_swapext sxp; if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; error = xfs_swapext(&sxp); mnt_drop_write_file(filp); return -error; } case XFS_IOC_FSCOUNTS: { xfs_fsop_counts_t out; error = xfs_fs_counts(mp, &out); if (error) return -error; if (copy_to_user(arg, &out, sizeof(out))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_SET_RESBLKS: { xfs_fsop_resblks_t inout; __uint64_t in; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (mp->m_flags & XFS_MOUNT_RDONLY) return -XFS_ERROR(EROFS); if (copy_from_user(&inout, arg, sizeof(inout))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; /* input parameter is passed in resblks field of structure */ in = inout.resblks; error = xfs_reserve_blocks(mp, &in, &inout); mnt_drop_write_file(filp); if (error) return -error; if (copy_to_user(arg, &inout, sizeof(inout))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_GET_RESBLKS: { xfs_fsop_resblks_t out; if (!capable(CAP_SYS_ADMIN)) return -EPERM; error = xfs_reserve_blocks(mp, NULL, &out); if (error) return -error; if (copy_to_user(arg, &out, sizeof(out))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_FSGROWFSDATA: { xfs_growfs_data_t in; if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; error = xfs_growfs_data(mp, &in); mnt_drop_write_file(filp); return -error; } case XFS_IOC_FSGROWFSLOG: { xfs_growfs_log_t in; if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; error = xfs_growfs_log(mp, &in); mnt_drop_write_file(filp); return -error; } case XFS_IOC_FSGROWFSRT: { xfs_growfs_rt_t in; if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); error = mnt_want_write_file(filp); if (error) return error; error = xfs_growfs_rt(mp, &in); mnt_drop_write_file(filp); return -error; } case XFS_IOC_GOINGDOWN: { __uint32_t in; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(in, (__uint32_t __user *)arg)) return -XFS_ERROR(EFAULT); error = xfs_fs_goingdown(mp, in); return -error; } case XFS_IOC_ERROR_INJECTION: { xfs_error_injection_t in; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (copy_from_user(&in, arg, sizeof(in))) return -XFS_ERROR(EFAULT); error = xfs_errortag_add(in.errtag, mp); return -error; } case XFS_IOC_ERROR_CLEARALL: if (!capable(CAP_SYS_ADMIN)) return -EPERM; error = xfs_errortag_clearall(mp, 1); return -error; case XFS_IOC_FREE_EOFBLOCKS: { struct xfs_eofblocks eofb; if (copy_from_user(&eofb, arg, sizeof(eofb))) return -XFS_ERROR(EFAULT); if (eofb.eof_version != XFS_EOFBLOCKS_VERSION) return -XFS_ERROR(EINVAL); if (eofb.eof_flags & ~XFS_EOF_FLAGS_VALID) return -XFS_ERROR(EINVAL); if (memchr_inv(&eofb.pad32, 0, sizeof(eofb.pad32)) || memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64))) return -XFS_ERROR(EINVAL); error = xfs_icache_free_eofblocks(mp, &eofb); return -error; } default: return -ENOTTY; } }
int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method) { unsigned short protocol; unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; if(skb == NULL) return -1; if((method <= NAT25_MIN) || (method >= NAT25_MAX)) return -1; protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); /*---------------------------------------------------*/ /* Handle IP frame */ /*---------------------------------------------------*/ if(protocol == __constant_htons(ETH_P_IP)) { struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN); if(((unsigned char*)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) { DEBUG_WARN("NAT25: malformed IP packet !\n"); return -1; } switch(method) { case NAT25_CHECK: return -1; case NAT25_INSERT: { //some muticast with source IP is all zero, maybe other case is illegal //in class A, B, C, host address is all zero or all one is illegal if (iph->saddr == 0) return 0; DEBUG_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); //record source IP address and , source mac address into db __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); } return 0; case NAT25_LOOKUP: { DEBUG_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); #ifdef SUPPORT_TX_MCAST2UNI if (priv->pshare->rf_ft_var.mc2u_disable || ((((OPMODE & (WIFI_STATION_STATE|WIFI_ASOC_STATE)) == (WIFI_STATION_STATE|WIFI_ASOC_STATE)) && !checkIPMcAndReplace(priv, skb, &iph->daddr)) || (OPMODE & WIFI_ADHOC_STATE))) #endif { __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { if (*((unsigned char *)&iph->daddr + 3) == 0xff) { // L2 is unicast but L3 is broadcast, make L2 bacome broadcast DEBUG_INFO("NAT25: Set DA as boardcast\n"); set_broadcast_mac_addr(skb->data); } else { // forward unknow IP packet to upper TCP/IP DEBUG_INFO("NAT25: Replace DA with BR's MAC\n"); if ( is_zero_mac_addr(priv->br_mac) ) { void netdev_br_init(struct net_device *netdev); printk("Re-init netdev_br_init() due to br_mac==0!\n"); netdev_br_init(priv->pnetdev); } copy_mac_addr(skb->data, priv->br_mac); } } } } return 0; default: return -1; } } /*---------------------------------------------------*/ /* Handle ARP frame */ /*---------------------------------------------------*/ else if(protocol == __constant_htons(ETH_P_ARP)) { struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); unsigned char *arp_ptr = (unsigned char *)(arp + 1); unsigned int *sender, *target; if(arp->ar_pro != __constant_htons(ETH_P_IP)) { DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); return -1; } switch(method) { case NAT25_CHECK: return 0; // skb_copy for all ARP frame case NAT25_INSERT: { DEBUG_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); // change to ARP sender mac address to wlan STA address copy_mac_addr(arp_ptr, GET_MY_HWADDR(priv)); arp_ptr += arp->ar_hln; sender = (unsigned int *)arp_ptr; __nat25_generate_ipv4_network_addr(networkAddr, sender); __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); } return 0; case NAT25_LOOKUP: { DEBUG_INFO("NAT25: Lookup ARP\n"); arp_ptr += arp->ar_hln; sender = (unsigned int *)arp_ptr; arp_ptr += (arp->ar_hln + arp->ar_pln); target = (unsigned int *)arp_ptr; __nat25_generate_ipv4_network_addr(networkAddr, target); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); // change to ARP target mac address to Lookup result arp_ptr = (unsigned char *)(arp + 1); arp_ptr += (arp->ar_hln + arp->ar_pln); copy_mac_addr(arp_ptr, skb->data); } return 0; default: return -1; } } /*---------------------------------------------------*/ /* Handle IPX and Apple Talk frame */ /*---------------------------------------------------*/ else if((protocol == __constant_htons(ETH_P_IPX)) || (protocol <= __constant_htons(ETH_FRAME_LEN))) { struct ipxhdr *ipx = NULL; struct elapaarp *ea = NULL; struct ddpehdr *ddp = NULL; unsigned char *framePtr = skb->data + ETH_HLEN; if(protocol == __constant_htons(ETH_P_IPX)) { DEBUG_INFO("NAT25: Protocol=IPX (Ethernet II)\n"); ipx = (struct ipxhdr *)framePtr; } else if(protocol <= __constant_htons(ETH_FRAME_LEN)) { if(RTW_RN16(framePtr) == 0xffff) { DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n"); ipx = (struct ipxhdr *)framePtr; } else { unsigned char ipx_8022_type = 0xE0; unsigned char snap_8022_type = 0xAA; if(*framePtr == snap_8022_type) { static const u8 ipx_snap_id[5] = {0x00, 0x00, 0x00, 0x81, 0x37}; // IPX SNAP ID static const u8 aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; // Apple Talk AARP SNAP ID static const u8 ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; // Apple Talk DDP SNAP ID framePtr += 3; // eliminate the 802.2 header if(!memcmp(ipx_snap_id, framePtr, 5)) { framePtr += 5; // eliminate the SNAP header DEBUG_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n"); ipx = (struct ipxhdr *)framePtr; } else if(!memcmp(aarp_snap_id, framePtr, 5)) { framePtr += 5; // eliminate the SNAP header ea = (struct elapaarp *)framePtr; } else if(!memcmp(ddp_snap_id, framePtr, 5)) { framePtr += 5; // eliminate the SNAP header ddp = (struct ddpehdr *)framePtr; } else { DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], framePtr[1], framePtr[2], framePtr[3], framePtr[4]); return -1; } } else if(*framePtr == ipx_8022_type) { framePtr += 3; // eliminate the 802.2 header if (RTW_RN16(framePtr) == 0xffff) { DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n"); ipx = (struct ipxhdr *)framePtr; } else return -1; } else return -1; } } else return -1; /* IPX */ if(ipx != NULL) { switch(method) { case NAT25_CHECK: if(mac_addr_equal(skb->data+ETH_ALEN, ipx->ipx_source.node)) { DEBUG_INFO("NAT25: Check IPX skb_copy\n"); return 0; } return -1; case NAT25_INSERT: { DEBUG_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", ipx->ipx_dest.net, ipx->ipx_dest.node[0], ipx->ipx_dest.node[1], ipx->ipx_dest.node[2], ipx->ipx_dest.node[3], ipx->ipx_dest.node[4], ipx->ipx_dest.node[5], ipx->ipx_dest.sock, ipx->ipx_source.net, ipx->ipx_source.node[0], ipx->ipx_source.node[1], ipx->ipx_source.node[2], ipx->ipx_source.node[3], ipx->ipx_source.node[4], ipx->ipx_source.node[5], ipx->ipx_source.sock); if(mac_addr_equal(skb->data+ETH_ALEN, ipx->ipx_source.node)) { DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n"); __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); // change IPX source node addr to wlan STA address copy_mac_addr(ipx->ipx_source.node, GET_MY_HWADDR(priv)); } else { __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); } __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); } return 0; case NAT25_LOOKUP: { if(mac_addr_equal(GET_MY_HWADDR(priv), ipx->ipx_dest.node)) { DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); // replace IPX destination node addr with Lookup destination MAC addr copy_mac_addr(ipx->ipx_dest.node, skb->data); } else { __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); } } return 0; default: return -1; } } /* AARP */ else if(ea != NULL) { /* Sanity check fields. */ if(ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n"); return -1; } switch(method) { case NAT25_CHECK: return 0; case NAT25_INSERT: { // change to AARP source mac address to wlan STA address copy_mac_addr(ea->hw_src, GET_MY_HWADDR(priv)); DEBUG_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", ea->pa_src_net, ea->pa_src_node, ea->pa_dst_net, ea->pa_dst_node); __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); } return 0; case NAT25_LOOKUP: { DEBUG_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", ea->pa_src_net, ea->pa_src_node, ea->pa_dst_net, ea->pa_dst_node); __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); // change to AARP destination mac address to Lookup result copy_mac_addr(ea->hw_dst, skb->data); } return 0; default: return -1; } } /* DDP */ else if(ddp != NULL) { switch(method) { case NAT25_CHECK: return -1; case NAT25_INSERT: { DEBUG_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", ddp->deh_snet, ddp->deh_snode, ddp->deh_dnet, ddp->deh_dnode); __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); } return 0; case NAT25_LOOKUP: { DEBUG_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", ddp->deh_snet, ddp->deh_snode, ddp->deh_dnet, ddp->deh_dnode); __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); } return 0; default: return -1; } } return -1; } /*---------------------------------------------------*/ /* Handle PPPoE frame */ /*---------------------------------------------------*/ else if((protocol == __constant_htons(ETH_P_PPP_DISC)) || (protocol == __constant_htons(ETH_P_PPP_SES))) { struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); unsigned short *pMagic; switch(method) { case NAT25_CHECK: if (ph->sid == 0) return 0; return 1; case NAT25_INSERT: if(ph->sid == 0) // Discovery phase according to tag { if(ph->code == PADI_CODE || ph->code == PADR_CODE) { if (priv->ethBrExtInfo.addPPPoETag) { struct pppoe_tag *tag, *pOldTag; unsigned char tag_buf[40]; int old_tag_len=0; tag = (struct pppoe_tag *)tag_buf; pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); if (pOldTag) { // if SID existed, copy old value and delete it old_tag_len = ntohs(pOldTag->tag_len); if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { DEBUG_ERR("SID tag length too long!\n"); return -1; } memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN, pOldTag->tag_data, old_tag_len); if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) { DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n"); return -1; } ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len); } tag->tag_type = PTT_RELAY_SID; tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len); // insert the magic_code+client mac in relay tag pMagic = (unsigned short *)tag->tag_data; *pMagic = htons(MAGIC_CODE); copy_mac_addr(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN); //Add relay tag if(__nat25_add_pppoe_tag(skb, tag) < 0) return -1; DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n", (ph->code == PADI_CODE ? "PADI" : "PADR")); } else { // not add relay tag if (priv->pppoe_connection_in_progress && !mac_addr_equal(skb->data+ETH_ALEN, priv->pppoe_addr)) { DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); return -2; } if (priv->pppoe_connection_in_progress == 0) copy_mac_addr(priv->pppoe_addr, skb->data+ETH_ALEN); priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; } } else return -1; } else // session phase { DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); if (!priv->ethBrExtInfo.addPPPoETag && priv->pppoe_connection_in_progress && mac_addr_equal(skb->data+ETH_ALEN, priv->pppoe_addr)) priv->pppoe_connection_in_progress = 0; } return 0; case NAT25_LOOKUP: if(ph->code == PADO_CODE || ph->code == PADS_CODE) { if (priv->ethBrExtInfo.addPPPoETag) { struct pppoe_tag *tag; unsigned char *ptr; unsigned short tagType, tagLen; int offset=0; if((ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID))) == 0) { DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n"); return -1; } tag = (struct pppoe_tag *)ptr; tagType = RTW_RB16(&ptr[0]); tagLen = RTW_RB16(&ptr[2]); if((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) { DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); return -1; } pMagic = (unsigned short *)tag->tag_data; if (ntohs(*pMagic) != MAGIC_CODE) { DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n", (ph->code == PADO_CODE ? "PADO" : "PADS")); return -1; } copy_mac_addr(skb->data, tag->tag_data+MAGIC_CODE_LEN); if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN) offset = TAG_HDR_LEN; if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) { DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n"); return -1; } ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset)); if (offset > 0) tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN); DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n", (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); } else { // not add relay tag if (!priv->pppoe_connection_in_progress) { DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n"); return -1; } copy_mac_addr(skb->data, priv->pppoe_addr); priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; } } else { if(ph->sid != 0) { DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); __nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid)); __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); __nat25_db_print(priv); } else return -1; } return 0; default: return -1; } } /*---------------------------------------------------*/ /* Handle EAP frame */ /*---------------------------------------------------*/ else if(protocol == __constant_htons(0x888e)) { switch(method) { case NAT25_CHECK: return -1; case NAT25_INSERT: return 0; case NAT25_LOOKUP: return 0; default: return -1; } } /*---------------------------------------------------*/ /* Handle C-Media proprietary frame */ /*---------------------------------------------------*/ else if((protocol == __constant_htons(0xe2ae)) || (protocol == __constant_htons(0xe2af))) { switch(method) { case NAT25_CHECK: return -1; case NAT25_INSERT: return 0; case NAT25_LOOKUP: return 0; default: return -1; } } /*---------------------------------------------------*/ /* Handle IPV6 frame */ /*---------------------------------------------------*/ #ifdef CL_IPV6_PASS else if(protocol == __constant_htons(ETH_P_IPV6)) { struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { DEBUG_WARN("NAT25: malformed IPv6 packet !\n"); return -1; } switch(method) { case NAT25_CHECK: if (skb->data[0] & 1) return 0; return -1; case NAT25_INSERT: { DEBUG_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3], iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7], iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3], iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]); if (memchr_inv(&iph->saddr, 0, 16)) { __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); __nat25_db_print(priv); if (iph->nexthdr == IPPROTO_ICMPV6 && skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) { struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); hdr->icmp6_cksum = 0; hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, iph->payload_len, IPPROTO_ICMPV6, csum_partial((__u8 *)hdr, iph->payload_len, 0)); } } } } return 0; case NAT25_LOOKUP: DEBUG_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3], iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7], iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3], iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]); __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { #ifdef SUPPORT_RX_UNI2MCAST if (iph->daddr.s6_addr[0] == 0xff) convert_ipv6_mac_to_mc(skb); #endif } return 0; default: return -1; } } #endif // CL_IPV6_PASS return -1; }
static int all_jid_bits_clear(char *lvb) { return !memchr_inv(lvb + JID_BITMAP_OFFSET, 0, GDLM_LVB_SIZE - JID_BITMAP_OFFSET); }
static int page_is_zero(struct page *p, unsigned int offset, size_t len) { return !memchr_inv(page_address(p) + offset, 0, len); }
static int igt_dmabuf_import(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *obj_map, *dma_map; u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; int err, i; dmabuf = mock_dmabuf(1); if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); if (IS_ERR(obj)) { pr_err("i915_gem_prime_import failed with err=%d\n", (int)PTR_ERR(obj)); err = PTR_ERR(obj); goto out_dmabuf; } if (obj->base.dev != &i915->drm) { pr_err("i915_gem_prime_import created a non-i915 object!\n"); err = -EINVAL; goto out_obj; } if (obj->base.size != PAGE_SIZE) { pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", (long long)obj->base.size, PAGE_SIZE); err = -EINVAL; goto out_obj; } dma_map = dma_buf_vmap(dmabuf); if (!dma_map) { pr_err("dma_buf_vmap failed\n"); err = -ENOMEM; goto out_obj; } if (0) { /* Can not yet map dmabuf */ obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(obj_map)) { err = PTR_ERR(obj_map); pr_err("i915_gem_object_pin_map failed with err=%d\n", err); goto out_dma_map; } for (i = 0; i < ARRAY_SIZE(pattern); i++) { memset(dma_map, pattern[i], PAGE_SIZE); if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { err = -EINVAL; pr_err("imported vmap not all set to %x!\n", pattern[i]); i915_gem_object_unpin_map(obj); goto out_dma_map; } } for (i = 0; i < ARRAY_SIZE(pattern); i++) { memset(obj_map, pattern[i], PAGE_SIZE); if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { err = -EINVAL; pr_err("exported vmap not all set to %x!\n", pattern[i]); i915_gem_object_unpin_map(obj); goto out_dma_map; } } i915_gem_object_unpin_map(obj); } err = 0; out_dma_map: dma_buf_vunmap(dmabuf, dma_map); out_obj: i915_gem_object_put(obj); out_dmabuf: dma_buf_put(dmabuf); return err; }
static int igt_dmabuf_export_kmap(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *ptr; int err; obj = i915_gem_object_create(i915, 2*PAGE_SIZE); if (IS_ERR(obj)) return PTR_ERR(obj); dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); i915_gem_object_put(obj); if (IS_ERR(dmabuf)) { err = PTR_ERR(dmabuf); pr_err("i915_gem_prime_export failed with err=%d\n", err); return err; } ptr = dma_buf_kmap(dmabuf, 0); if (!ptr) { pr_err("dma_buf_kmap failed\n"); err = -ENOMEM; goto err; } if (memchr_inv(ptr, 0, PAGE_SIZE)) { dma_buf_kunmap(dmabuf, 0, ptr); pr_err("Exported page[0] not initialiased to zero!\n"); err = -EINVAL; goto err; } memset(ptr, 0xc5, PAGE_SIZE); dma_buf_kunmap(dmabuf, 0, ptr); ptr = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(ptr)) { err = PTR_ERR(ptr); pr_err("i915_gem_object_pin_map failed with err=%d\n", err); goto err; } memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE); i915_gem_object_unpin_map(obj); ptr = dma_buf_kmap(dmabuf, 1); if (!ptr) { pr_err("dma_buf_kmap failed\n"); err = -ENOMEM; goto err; } if (memchr_inv(ptr, 0xaa, PAGE_SIZE)) { dma_buf_kunmap(dmabuf, 1, ptr); pr_err("Exported page[1] not set to 0xaa!\n"); err = -EINVAL; goto err; } memset(ptr, 0xc5, PAGE_SIZE); dma_buf_kunmap(dmabuf, 1, ptr); ptr = dma_buf_kmap(dmabuf, 0); if (!ptr) { pr_err("dma_buf_kmap failed\n"); err = -ENOMEM; goto err; } if (memchr_inv(ptr, 0xc5, PAGE_SIZE)) { dma_buf_kunmap(dmabuf, 0, ptr); pr_err("Exported page[0] did not retain 0xc5!\n"); err = -EINVAL; goto err; } dma_buf_kunmap(dmabuf, 0, ptr); ptr = dma_buf_kmap(dmabuf, 2); if (ptr) { pr_err("Erroneously kmapped beyond the end of the object!\n"); dma_buf_kunmap(dmabuf, 2, ptr); err = -EINVAL; goto err; } ptr = dma_buf_kmap(dmabuf, -1); if (ptr) { pr_err("Erroneously kmapped before the start of the object!\n"); dma_buf_kunmap(dmabuf, -1, ptr); err = -EINVAL; goto err; } err = 0; err: dma_buf_put(dmabuf); return err; }
long __keyctl_dh_compute(struct keyctl_dh_params __user *params, char __user *buffer, size_t buflen, struct keyctl_kdf_params *kdfcopy) { long ret; ssize_t dlen; int secretlen; int outlen; struct keyctl_dh_params pcopy; struct dh dh_inputs; struct scatterlist outsg; struct dh_completion compl; struct crypto_kpp *tfm; struct kpp_request *req; uint8_t *secret; uint8_t *outbuf; struct kdf_sdesc *sdesc = NULL; if (!params || (!buffer && buflen)) { ret = -EINVAL; goto out1; } if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { ret = -EFAULT; goto out1; } if (kdfcopy) { char *hashname; if (memchr_inv(kdfcopy->__spare, 0, sizeof(kdfcopy->__spare))) { ret = -EINVAL; goto out1; } if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { ret = -EMSGSIZE; goto out1; } /* get KDF name string */ hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); if (IS_ERR(hashname)) { ret = PTR_ERR(hashname); goto out1; } /* allocate KDF from the kernel crypto API */ ret = kdf_alloc(&sdesc, hashname); kfree(hashname); if (ret) goto out1; } memset(&dh_inputs, 0, sizeof(dh_inputs)); dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); if (dlen < 0) { ret = dlen; goto out1; } dh_inputs.p_size = dlen; dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); if (dlen < 0) { ret = dlen; goto out2; } dh_inputs.g_size = dlen; dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); if (dlen < 0) { ret = dlen; goto out2; } dh_inputs.key_size = dlen; secretlen = crypto_dh_key_len(&dh_inputs); secret = kmalloc(secretlen, GFP_KERNEL); if (!secret) { ret = -ENOMEM; goto out2; } ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); if (ret) goto out3; tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0); if (IS_ERR(tfm)) { ret = PTR_ERR(tfm); goto out3; } ret = crypto_kpp_set_secret(tfm, secret, secretlen); if (ret) goto out4; outlen = crypto_kpp_maxsize(tfm); if (!kdfcopy) { /* * When not using a KDF, buflen 0 is used to read the * required buffer length */ if (buflen == 0) { ret = outlen; goto out4; } else if (outlen > buflen) { ret = -EOVERFLOW; goto out4; } } outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen, GFP_KERNEL); if (!outbuf) { ret = -ENOMEM; goto out4; } sg_init_one(&outsg, outbuf, outlen); req = kpp_request_alloc(tfm, GFP_KERNEL); if (!req) { ret = -ENOMEM; goto out5; } kpp_request_set_input(req, NULL, 0); kpp_request_set_output(req, &outsg, outlen); init_completion(&compl.completion); kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, dh_crypto_done, &compl); /* * For DH, generate_public_key and generate_shared_secret are * the same calculation */ ret = crypto_kpp_generate_public_key(req); if (ret == -EINPROGRESS) { wait_for_completion(&compl.completion); ret = compl.err; if (ret) goto out6; } if (kdfcopy) { /* * Concatenate SP800-56A otherinfo past DH shared secret -- the * input to the KDF is (DH shared secret || otherinfo) */ if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo, kdfcopy->otherinfolen) != 0) { ret = -EFAULT; goto out6; } ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf, req->dst_len + kdfcopy->otherinfolen, outlen - req->dst_len); } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) { ret = req->dst_len; } else { ret = -EFAULT; } out6: kpp_request_free(req); out5: kzfree(outbuf); out4: crypto_free_kpp(tfm); out3: kzfree(secret); out2: dh_free_data(&dh_inputs); out1: kdf_dealloc(sdesc); return ret; }