Revision 4b658d1bbc16605330694bb3ef2570c465ef383d authored by Leon Romanovsky on 25 March 2018, 08:23:55 UTC, committed by Jason Gunthorpe on 27 March 2018, 20:10:45 UTC
Add missing check that device is connected prior to access it. [ 55.358652] BUG: KASAN: null-ptr-deref in rdma_init_qp_attr+0x4a/0x2c0 [ 55.359389] Read of size 8 at addr 00000000000000b0 by task qp/618 [ 55.360255] [ 55.360432] CPU: 1 PID: 618 Comm: qp Not tainted 4.16.0-rc1-00071-gcaf61b1b8b88 #91 [ 55.361693] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014 [ 55.363264] Call Trace: [ 55.363833] dump_stack+0x5c/0x77 [ 55.364215] kasan_report+0x163/0x380 [ 55.364610] ? rdma_init_qp_attr+0x4a/0x2c0 [ 55.365238] rdma_init_qp_attr+0x4a/0x2c0 [ 55.366410] ucma_init_qp_attr+0x111/0x200 [ 55.366846] ? ucma_notify+0xf0/0xf0 [ 55.367405] ? _get_random_bytes+0xea/0x1b0 [ 55.367846] ? urandom_read+0x2f0/0x2f0 [ 55.368436] ? kmem_cache_alloc_trace+0xd2/0x1e0 [ 55.369104] ? refcount_inc_not_zero+0x9/0x60 [ 55.369583] ? refcount_inc+0x5/0x30 [ 55.370155] ? rdma_create_id+0x215/0x240 [ 55.370937] ? _copy_to_user+0x4f/0x60 [ 55.371620] ? mem_cgroup_commit_charge+0x1f5/0x290 [ 55.372127] ? _copy_from_user+0x5e/0x90 [ 55.372720] ucma_write+0x174/0x1f0 [ 55.373090] ? ucma_close_id+0x40/0x40 [ 55.373805] ? __lru_cache_add+0xa8/0xd0 [ 55.374403] __vfs_write+0xc4/0x350 [ 55.374774] ? kernel_read+0xa0/0xa0 [ 55.375173] ? fsnotify+0x899/0x8f0 [ 55.375544] ? fsnotify_unmount_inodes+0x170/0x170 [ 55.376689] ? __fsnotify_update_child_dentry_flags+0x30/0x30 [ 55.377522] ? handle_mm_fault+0x174/0x320 [ 55.378169] vfs_write+0xf7/0x280 [ 55.378864] SyS_write+0xa1/0x120 [ 55.379270] ? SyS_read+0x120/0x120 [ 55.379643] ? mm_fault_error+0x180/0x180 [ 55.380071] ? task_work_run+0x7d/0xd0 [ 55.380910] ? __task_pid_nr_ns+0x120/0x140 [ 55.381366] ? SyS_read+0x120/0x120 [ 55.381739] do_syscall_64+0xeb/0x250 [ 55.382143] entry_SYSCALL_64_after_hwframe+0x21/0x86 [ 55.382841] RIP: 0033:0x7fc2ef803e99 [ 55.383227] RSP: 002b:00007fffcc5f3be8 EFLAGS: 00000217 ORIG_RAX: 0000000000000001 [ 55.384173] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fc2ef803e99 [ 55.386145] RDX: 0000000000000057 RSI: 0000000020000080 RDI: 0000000000000003 [ 55.388418] RBP: 00007fffcc5f3c00 R08: 0000000000000000 R09: 0000000000000000 [ 55.390542] R10: 0000000000000000 R11: 0000000000000217 R12: 0000000000400480 [ 55.392916] R13: 00007fffcc5f3cf0 R14: 0000000000000000 R15: 0000000000000000 [ 55.521088] Code: e5 4d 1e ff 48 89 df 44 0f b6 b3 b8 01 00 00 e8 65 50 1e ff 4c 8b 2b 49 8d bd b0 00 00 00 e8 56 50 1e ff 41 0f b6 c6 48 c1 e0 04 <49> 03 85 b0 00 00 00 48 8d 78 08 48 89 04 24 e8 3a 4f 1e ff 48 [ 55.525980] RIP: rdma_init_qp_attr+0x52/0x2c0 RSP: ffff8801e2c2f9d8 [ 55.532648] CR2: 00000000000000b0 [ 55.534396] ---[ end trace 70cee64090251c0b ]--- Fixes: 75216638572f ("RDMA/cma: Export rdma cm interface to userspace") Fixes: d541e45500bd ("IB/core: Convert ah_attr from OPA to IB when copying to user") Reported-by: <syzbot+7b62c837c2516f8f38c8@syzkaller.appspotmail.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
1 parent 9137108
conmakehash.c
/*
* conmakehash.c
*
* Create arrays for initializing the kernel folded tables (using a hash
* table turned out to be to limiting...) Unfortunately we can't simply
* preinitialize the tables at compile time since kfree() cannot accept
* memory not allocated by kmalloc(), and doing our own memory management
* just for this seems like massive overkill.
*
* Copyright (C) 1995-1997 H. Peter Anvin
*
* This program is a part of the Linux kernel, and may be freely
* copied under the terms of the GNU General Public License (GPL),
* version 2, or at your option any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <string.h>
#include <ctype.h>
#define MAX_FONTLEN 256
typedef unsigned short unicode;
static void usage(char *argv0)
{
fprintf(stderr, "Usage: \n"
" %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
exit(EX_USAGE);
}
static int getunicode(char **p0)
{
char *p = *p0;
while (*p == ' ' || *p == '\t')
p++;
if (*p != 'U' || p[1] != '+' ||
!isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
!isxdigit(p[5]) || isxdigit(p[6]))
return -1;
*p0 = p+6;
return strtol(p+2,0,16);
}
unicode unitable[MAX_FONTLEN][255];
/* Massive overkill, but who cares? */
int unicount[MAX_FONTLEN];
static void addpair(int fp, int un)
{
int i;
if ( un <= 0xfffe )
{
/* Check it isn't a duplicate */
for ( i = 0 ; i < unicount[fp] ; i++ )
if ( unitable[fp][i] == un )
return;
/* Add to list */
if ( unicount[fp] > 254 )
{
fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
exit(EX_DATAERR);
}
unitable[fp][unicount[fp]] = un;
unicount[fp]++;
}
/* otherwise: ignore */
}
int main(int argc, char *argv[])
{
FILE *ctbl;
char *tblname;
char buffer[65536];
int fontlen;
int i, nuni, nent;
int fp0, fp1, un0, un1;
char *p, *p1;
if ( argc < 2 || argc > 5 )
usage(argv[0]);
if ( !strcmp(argv[1],"-") )
{
ctbl = stdin;
tblname = "stdin";
}
else
{
ctbl = fopen(tblname = argv[1], "r");
if ( !ctbl )
{
perror(tblname);
exit(EX_NOINPUT);
}
}
/* For now we assume the default font is always 256 characters. */
fontlen = 256;
/* Initialize table */
for ( i = 0 ; i < fontlen ; i++ )
unicount[i] = 0;
/* Now we come to the tricky part. Parse the input table. */
while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
{
if ( (p = strchr(buffer, '\n')) != NULL )
*p = '\0';
else
fprintf(stderr, "%s: Warning: line too long\n", tblname);
p = buffer;
/*
* Syntax accepted:
* <fontpos> <unicode> <unicode> ...
* <range> idem
* <range> <unicode range>
*
* where <range> ::= <fontpos>-<fontpos>
* and <unicode> ::= U+<h><h><h><h>
* and <h> ::= <hexadecimal digit>
*/
while (*p == ' ' || *p == '\t')
p++;
if (!*p || *p == '#')
continue; /* skip comment or blank line */
fp0 = strtol(p, &p1, 0);
if (p1 == p)
{
fprintf(stderr, "Bad input line: %s\n", buffer);
exit(EX_DATAERR);
}
p = p1;
while (*p == ' ' || *p == '\t')
p++;
if (*p == '-')
{
p++;
fp1 = strtol(p, &p1, 0);
if (p1 == p)
{
fprintf(stderr, "Bad input line: %s\n", buffer);
exit(EX_DATAERR);
}
p = p1;
}
else
fp1 = 0;
if ( fp0 < 0 || fp0 >= fontlen )
{
fprintf(stderr,
"%s: Glyph number (0x%x) larger than font length\n",
tblname, fp0);
exit(EX_DATAERR);
}
if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
{
fprintf(stderr,
"%s: Bad end of range (0x%x)\n",
tblname, fp1);
exit(EX_DATAERR);
}
if (fp1)
{
/* we have a range; expect the word "idem" or a Unicode range of the
same length */
while (*p == ' ' || *p == '\t')
p++;
if (!strncmp(p, "idem", 4))
{
for (i=fp0; i<=fp1; i++)
addpair(i,i);
p += 4;
}
else
{
un0 = getunicode(&p);
while (*p == ' ' || *p == '\t')
p++;
if (*p != '-')
{
fprintf(stderr,
"%s: Corresponding to a range of font positions, there should be a Unicode range\n",
tblname);
exit(EX_DATAERR);
}
p++;
un1 = getunicode(&p);
if (un0 < 0 || un1 < 0)
{
fprintf(stderr,
"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
tblname, fp0, fp1);
exit(EX_DATAERR);
}
if (un1 - un0 != fp1 - fp0)
{
fprintf(stderr,
"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
tblname, un0, un1, fp0, fp1);
exit(EX_DATAERR);
}
for(i=fp0; i<=fp1; i++)
addpair(i,un0-fp0+i);
}
}
else
{
/* no range; expect a list of unicode values for a single font position */
while ( (un0 = getunicode(&p)) >= 0 )
addpair(fp0, un0);
}
while (*p == ' ' || *p == '\t')
p++;
if (*p && *p != '#')
fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
}
/* Okay, we hit EOF, now output hash table */
fclose(ctbl);
/* Compute total size of Unicode list */
nuni = 0;
for ( i = 0 ; i < fontlen ; i++ )
nuni += unicount[i];
printf("\
/*\n\
* Do not edit this file; it was automatically generated by\n\
*\n\
* conmakehash %s > [this file]\n\
*\n\
*/\n\
\n\
#include <linux/types.h>\n\
\n\
u8 dfont_unicount[%d] = \n\
{\n\t", argv[1], fontlen);
for ( i = 0 ; i < fontlen ; i++ )
{
printf("%3d", unicount[i]);
if ( i == fontlen-1 )
printf("\n};\n");
else if ( i % 8 == 7 )
printf(",\n\t");
else
printf(", ");
}
printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
fp0 = 0;
nent = 0;
for ( i = 0 ; i < nuni ; i++ )
{
while ( nent >= unicount[fp0] )
{
fp0++;
nent = 0;
}
printf("0x%04x", unitable[fp0][nent++]);
if ( i == nuni-1 )
printf("\n};\n");
else if ( i % 8 == 7 )
printf(",\n\t");
else
printf(", ");
}
exit(EX_OK);
}
Computing file changes ...