2019-05-20 09:19:02 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-01-25 17:00:00 -03:00
/*
* altera . c
*
* altera FPGA driver
*
* Copyright ( C ) Altera Corporation 1998 - 2001
* Copyright ( C ) 2010 , 2011 NetUP Inc .
* Copyright ( C ) 2010 , 2011 Igor M . Liplianin < liplianin @ netup . ru >
*/
# include <asm/unaligned.h>
# include <linux/ctype.h>
# include <linux/string.h>
# include <linux/firmware.h>
# include <linux/slab.h>
2011-07-03 15:49:50 -04:00
# include <linux/module.h>
2011-09-23 11:17:41 -03:00
# include <misc/altera.h>
2011-01-25 17:00:00 -03:00
# include "altera-exprt.h"
# include "altera-jtag.h"
static int debug = 1 ;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " enable debugging information " ) ;
MODULE_DESCRIPTION ( " altera FPGA kernel module " ) ;
MODULE_AUTHOR ( " Igor M. Liplianin <liplianin@netup.ru> " ) ;
MODULE_LICENSE ( " GPL " ) ;
# define dprintk(args...) \
if ( debug ) { \
printk ( KERN_DEBUG args ) ; \
}
enum altera_fpga_opcode {
OP_NOP = 0 ,
OP_DUP ,
OP_SWP ,
OP_ADD ,
OP_SUB ,
OP_MULT ,
OP_DIV ,
OP_MOD ,
OP_SHL ,
OP_SHR ,
OP_NOT ,
OP_AND ,
OP_OR ,
OP_XOR ,
OP_INV ,
OP_GT ,
OP_LT ,
OP_RET ,
OP_CMPS ,
OP_PINT ,
OP_PRNT ,
OP_DSS ,
OP_DSSC ,
OP_ISS ,
OP_ISSC ,
OP_DPR = 0x1c ,
OP_DPRL ,
OP_DPO ,
OP_DPOL ,
OP_IPR ,
OP_IPRL ,
OP_IPO ,
OP_IPOL ,
OP_PCHR ,
OP_EXIT ,
OP_EQU ,
OP_POPT ,
OP_ABS = 0x2c ,
OP_BCH0 ,
OP_PSH0 = 0x2f ,
OP_PSHL = 0x40 ,
OP_PSHV ,
OP_JMP ,
OP_CALL ,
OP_NEXT ,
OP_PSTR ,
OP_SINT = 0x47 ,
OP_ST ,
OP_ISTP ,
OP_DSTP ,
OP_SWPN ,
OP_DUPN ,
OP_POPV ,
OP_POPE ,
OP_POPA ,
OP_JMPZ ,
OP_DS ,
OP_IS ,
OP_DPRA ,
OP_DPOA ,
OP_IPRA ,
OP_IPOA ,
OP_EXPT ,
OP_PSHE ,
OP_PSHA ,
OP_DYNA ,
OP_EXPV = 0x5c ,
OP_COPY = 0x80 ,
OP_REVA ,
OP_DSC ,
OP_ISC ,
OP_WAIT ,
OP_VS ,
OP_CMPA = 0xc0 ,
OP_VSC ,
} ;
struct altera_procinfo {
char * name ;
u8 attrs ;
struct altera_procinfo * next ;
} ;
/* This function checks if enough parameters are available on the stack. */
static int altera_check_stack ( int stack_ptr , int count , int * status )
{
if ( stack_ptr < count ) {
* status = - EOVERFLOW ;
return 0 ;
}
return 1 ;
}
static void altera_export_int ( char * key , s32 value )
{
dprintk ( " Export: key = \" %s \" , value = %d \n " , key , value ) ;
}
# define HEX_LINE_CHARS 72
# define HEX_LINE_BITS (HEX_LINE_CHARS * 4)
static void altera_export_bool_array ( char * key , u8 * data , s32 count )
{
char string [ HEX_LINE_CHARS + 1 ] ;
s32 i , offset ;
u32 size , line , lines , linebits , value , j , k ;
if ( count > HEX_LINE_BITS ) {
dprintk ( " Export: key = \" %s \" , %d bits, value = HEX \n " ,
key , count ) ;
lines = ( count + ( HEX_LINE_BITS - 1 ) ) / HEX_LINE_BITS ;
for ( line = 0 ; line < lines ; + + line ) {
if ( line < ( lines - 1 ) ) {
linebits = HEX_LINE_BITS ;
size = HEX_LINE_CHARS ;
offset = count - ( ( line + 1 ) * HEX_LINE_BITS ) ;
} else {
linebits =
count - ( ( lines - 1 ) * HEX_LINE_BITS ) ;
size = ( linebits + 3 ) / 4 ;
offset = 0L ;
}
string [ size ] = ' \0 ' ;
j = size - 1 ;
value = 0 ;
for ( k = 0 ; k < linebits ; + + k ) {
i = k + offset ;
if ( data [ i > > 3 ] & ( 1 < < ( i & 7 ) ) )
value | = ( 1 < < ( i & 3 ) ) ;
if ( ( i & 3 ) = = 3 ) {
sprintf ( & string [ j ] , " %1x " , value ) ;
value = 0 ;
- - j ;
}
}
if ( ( k & 3 ) > 0 )
sprintf ( & string [ j ] , " %1x " , value ) ;
dprintk ( " %s \n " , string ) ;
}
} else {
size = ( count + 3 ) / 4 ;
string [ size ] = ' \0 ' ;
j = size - 1 ;
value = 0 ;
for ( i = 0 ; i < count ; + + i ) {
if ( data [ i > > 3 ] & ( 1 < < ( i & 7 ) ) )
value | = ( 1 < < ( i & 3 ) ) ;
if ( ( i & 3 ) = = 3 ) {
sprintf ( & string [ j ] , " %1x " , value ) ;
value = 0 ;
- - j ;
}
}
if ( ( i & 3 ) > 0 )
sprintf ( & string [ j ] , " %1x " , value ) ;
dprintk ( " Export: key = \" %s \" , %d bits, value = HEX %s \n " ,
key , count , string ) ;
}
}
static int altera_execute ( struct altera_state * astate ,
u8 * p ,
s32 program_size ,
s32 * error_address ,
int * exit_code ,
int * format_version )
{
struct altera_config * aconf = astate - > config ;
char * msg_buff = astate - > msg_buff ;
long * stack = astate - > stack ;
int status = 0 ;
u32 first_word = 0L ;
u32 action_table = 0L ;
u32 proc_table = 0L ;
u32 str_table = 0L ;
u32 sym_table = 0L ;
u32 data_sect = 0L ;
u32 code_sect = 0L ;
u32 debug_sect = 0L ;
u32 action_count = 0L ;
u32 proc_count = 0L ;
u32 sym_count = 0L ;
long * vars = NULL ;
s32 * var_size = NULL ;
char * attrs = NULL ;
u8 * proc_attributes = NULL ;
u32 pc ;
u32 opcode_address ;
u32 args [ 3 ] ;
u32 opcode ;
u32 name_id ;
u8 charbuf [ 4 ] ;
long long_tmp ;
u32 variable_id ;
u8 * charptr_tmp ;
u8 * charptr_tmp2 ;
long * longptr_tmp ;
int version = 0 ;
int delta = 0 ;
int stack_ptr = 0 ;
u32 arg_count ;
int done = 0 ;
int bad_opcode = 0 ;
u32 count ;
u32 index ;
u32 index2 ;
s32 long_count ;
s32 long_idx ;
s32 long_idx2 ;
u32 i ;
u32 j ;
u32 uncomp_size ;
u32 offset ;
u32 value ;
int current_proc = 0 ;
int reverse ;
char * name ;
dprintk ( " %s \n " , __func__ ) ;
/* Read header information */
if ( program_size > 52L ) {
first_word = get_unaligned_be32 ( & p [ 0 ] ) ;
version = ( first_word & 1L ) ;
* format_version = version + 1 ;
delta = version * 8 ;
action_table = get_unaligned_be32 ( & p [ 4 ] ) ;
proc_table = get_unaligned_be32 ( & p [ 8 ] ) ;
str_table = get_unaligned_be32 ( & p [ 4 + delta ] ) ;
sym_table = get_unaligned_be32 ( & p [ 16 + delta ] ) ;
data_sect = get_unaligned_be32 ( & p [ 20 + delta ] ) ;
code_sect = get_unaligned_be32 ( & p [ 24 + delta ] ) ;
debug_sect = get_unaligned_be32 ( & p [ 28 + delta ] ) ;
action_count = get_unaligned_be32 ( & p [ 40 + delta ] ) ;
proc_count = get_unaligned_be32 ( & p [ 44 + delta ] ) ;
sym_count = get_unaligned_be32 ( & p [ 48 + ( 2 * delta ) ] ) ;
}
if ( ( first_word ! = 0x4A414D00L ) & & ( first_word ! = 0x4A414D01L ) ) {
done = 1 ;
status = - EIO ;
goto exit_done ;
}
if ( sym_count < = 0 )
goto exit_done ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
vars = kcalloc ( sym_count , sizeof ( long ) , GFP_KERNEL ) ;
2011-01-25 17:00:00 -03:00
if ( vars = = NULL )
status = - ENOMEM ;
if ( status = = 0 ) {
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
var_size = kcalloc ( sym_count , sizeof ( s32 ) , GFP_KERNEL ) ;
2011-01-25 17:00:00 -03:00
if ( var_size = = NULL )
status = - ENOMEM ;
}
if ( status = = 0 ) {
attrs = kzalloc ( sym_count , GFP_KERNEL ) ;
if ( attrs = = NULL )
status = - ENOMEM ;
}
if ( ( status = = 0 ) & & ( version > 0 ) ) {
proc_attributes = kzalloc ( proc_count , GFP_KERNEL ) ;
if ( proc_attributes = = NULL )
status = - ENOMEM ;
}
if ( status ! = 0 )
goto exit_done ;
delta = version * 2 ;
for ( i = 0 ; i < sym_count ; + + i ) {
offset = ( sym_table + ( ( 11 + delta ) * i ) ) ;
value = get_unaligned_be32 ( & p [ offset + 3 + delta ] ) ;
attrs [ i ] = p [ offset ] ;
/*
* use bit 7 of attribute byte to indicate that
* this buffer was dynamically allocated
* and should be freed later
*/
attrs [ i ] & = 0x7f ;
var_size [ i ] = get_unaligned_be32 ( & p [ offset + 7 + delta ] ) ;
/*
* Attribute bits :
* bit 0 : 0 = read - only , 1 = read - write
* bit 1 : 0 = not compressed , 1 = compressed
* bit 2 : 0 = not initialized , 1 = initialized
* bit 3 : 0 = scalar , 1 = array
* bit 4 : 0 = Boolean , 1 = integer
* bit 5 : 0 = declared variable ,
* 1 = compiler created temporary variable
*/
if ( ( attrs [ i ] & 0x0c ) = = 0x04 )
/* initialized scalar variable */
vars [ i ] = value ;
else if ( ( attrs [ i ] & 0x1e ) = = 0x0e ) {
/* initialized compressed Boolean array */
uncomp_size = get_unaligned_le32 ( & p [ data_sect + value ] ) ;
/* allocate a buffer for the uncompressed data */
vars [ i ] = ( long ) kzalloc ( uncomp_size , GFP_KERNEL ) ;
if ( vars [ i ] = = 0L )
status = - ENOMEM ;
else {
/* set flag so buffer will be freed later */
attrs [ i ] | = 0x80 ;
/* uncompress the data */
if ( altera_shrink ( & p [ data_sect + value ] ,
var_size [ i ] ,
( u8 * ) vars [ i ] ,
uncomp_size ,
version ) ! = uncomp_size )
/* decompression failed */
status = - EIO ;
else
var_size [ i ] = uncomp_size * 8L ;
}
} else if ( ( attrs [ i ] & 0x1e ) = = 0x0c ) {
/* initialized Boolean array */
vars [ i ] = value + data_sect + ( long ) p ;
} else if ( ( attrs [ i ] & 0x1c ) = = 0x1c ) {
/* initialized integer array */
vars [ i ] = value + data_sect ;
} else if ( ( attrs [ i ] & 0x0c ) = = 0x08 ) {
/* uninitialized array */
/* flag attrs so that memory is freed */
attrs [ i ] | = 0x80 ;
if ( var_size [ i ] > 0 ) {
u32 size ;
if ( attrs [ i ] & 0x10 )
/* integer array */
size = ( var_size [ i ] * sizeof ( s32 ) ) ;
else
/* Boolean array */
size = ( ( var_size [ i ] + 7L ) / 8L ) ;
vars [ i ] = ( long ) kzalloc ( size , GFP_KERNEL ) ;
if ( vars [ i ] = = 0 ) {
status = - ENOMEM ;
} else {
/* zero out memory */
for ( j = 0 ; j < size ; + + j )
( ( u8 * ) ( vars [ i ] ) ) [ j ] = 0 ;
}
} else
vars [ i ] = 0 ;
} else
vars [ i ] = 0 ;
}
exit_done :
if ( status ! = 0 )
done = 1 ;
altera_jinit ( astate ) ;
pc = code_sect ;
msg_buff [ 0 ] = ' \0 ' ;
/*
* For JBC version 2 , we will execute the procedures corresponding to
* the selected ACTION
*/
if ( version > 0 ) {
if ( aconf - > action = = NULL ) {
status = - EINVAL ;
done = 1 ;
} else {
int action_found = 0 ;
for ( i = 0 ; ( i < action_count ) & & ! action_found ; + + i ) {
name_id = get_unaligned_be32 ( & p [ action_table +
( 12 * i ) ] ) ;
name = & p [ str_table + name_id ] ;
2014-10-13 15:54:50 -07:00
if ( strncasecmp ( aconf - > action , name , strlen ( name ) ) = = 0 ) {
2011-01-25 17:00:00 -03:00
action_found = 1 ;
current_proc =
get_unaligned_be32 ( & p [ action_table +
( 12 * i ) + 8 ] ) ;
}
}
if ( ! action_found ) {
status = - EINVAL ;
done = 1 ;
}
}
if ( status = = 0 ) {
int first_time = 1 ;
i = current_proc ;
while ( ( i ! = 0 ) | | first_time ) {
first_time = 0 ;
/* check procedure attribute byte */
proc_attributes [ i ] =
( p [ proc_table +
( 13 * i ) + 8 ] &
0x03 ) ;
/*
* BIT0 - OPTIONAL
* BIT1 - RECOMMENDED
* BIT6 - FORCED OFF
* BIT7 - FORCED ON
*/
i = get_unaligned_be32 ( & p [ proc_table +
( 13 * i ) + 4 ] ) ;
}
/*
* Set current_proc to the first procedure
* to be executed
*/
i = current_proc ;
while ( ( i ! = 0 ) & &
( ( proc_attributes [ i ] = = 1 ) | |
( ( proc_attributes [ i ] & 0xc0 ) = = 0x40 ) ) ) {
i = get_unaligned_be32 ( & p [ proc_table +
( 13 * i ) + 4 ] ) ;
}
if ( ( i ! = 0 ) | | ( ( i = = 0 ) & & ( current_proc = = 0 ) & &
( ( proc_attributes [ 0 ] ! = 1 ) & &
( ( proc_attributes [ 0 ] & 0xc0 ) ! = 0x40 ) ) ) ) {
current_proc = i ;
pc = code_sect +
get_unaligned_be32 ( & p [ proc_table +
( 13 * i ) + 9 ] ) ;
if ( ( pc < code_sect ) | | ( pc > = debug_sect ) )
status = - ERANGE ;
} else
/* there are no procedures to execute! */
done = 1 ;
}
}
msg_buff [ 0 ] = ' \0 ' ;
while ( ! done ) {
opcode = ( p [ pc ] & 0xff ) ;
opcode_address = pc ;
+ + pc ;
if ( debug > 1 )
printk ( " opcode: %02x \n " , opcode ) ;
arg_count = ( opcode > > 6 ) & 3 ;
for ( i = 0 ; i < arg_count ; + + i ) {
args [ i ] = get_unaligned_be32 ( & p [ pc ] ) ;
pc + = 4 ;
}
switch ( opcode ) {
case OP_NOP :
break ;
case OP_DUP :
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
stack [ stack_ptr ] = stack [ stack_ptr - 1 ] ;
+ + stack_ptr ;
}
break ;
case OP_SWP :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
long_tmp = stack [ stack_ptr - 2 ] ;
stack [ stack_ptr - 2 ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
break ;
case OP_ADD :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] + = stack [ stack_ptr ] ;
}
break ;
case OP_SUB :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] - = stack [ stack_ptr ] ;
}
break ;
case OP_MULT :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] * = stack [ stack_ptr ] ;
}
break ;
case OP_DIV :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] / = stack [ stack_ptr ] ;
}
break ;
case OP_MOD :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] % = stack [ stack_ptr ] ;
}
break ;
case OP_SHL :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] < < = stack [ stack_ptr ] ;
}
break ;
case OP_SHR :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] > > = stack [ stack_ptr ] ;
}
break ;
case OP_NOT :
if ( altera_check_stack ( stack_ptr , 1 , & status ) )
stack [ stack_ptr - 1 ] ^ = ( - 1L ) ;
break ;
case OP_AND :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] & = stack [ stack_ptr ] ;
}
break ;
case OP_OR :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] | = stack [ stack_ptr ] ;
}
break ;
case OP_XOR :
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
- - stack_ptr ;
stack [ stack_ptr - 1 ] ^ = stack [ stack_ptr ] ;
}
break ;
case OP_INV :
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
stack [ stack_ptr - 1 ] = stack [ stack_ptr - 1 ] ? 0L : 1L ;
break ;
case OP_GT :
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
- - stack_ptr ;
stack [ stack_ptr - 1 ] =
( stack [ stack_ptr - 1 ] > stack [ stack_ptr ] ) ?
1L : 0L ;
break ;
case OP_LT :
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
- - stack_ptr ;
stack [ stack_ptr - 1 ] =
( stack [ stack_ptr - 1 ] < stack [ stack_ptr ] ) ?
1L : 0L ;
break ;
case OP_RET :
if ( ( version > 0 ) & & ( stack_ptr = = 0 ) ) {
/*
* We completed one of the main procedures
* of an ACTION .
* Find the next procedure
* to be executed and jump to it .
* If there are no more procedures , then EXIT .
*/
i = get_unaligned_be32 ( & p [ proc_table +
( 13 * current_proc ) + 4 ] ) ;
while ( ( i ! = 0 ) & &
( ( proc_attributes [ i ] = = 1 ) | |
( ( proc_attributes [ i ] & 0xc0 ) = = 0x40 ) ) )
i = get_unaligned_be32 ( & p [ proc_table +
( 13 * i ) + 4 ] ) ;
if ( i = = 0 ) {
/* no procedures to execute! */
done = 1 ;
* exit_code = 0 ; /* success */
} else {
current_proc = i ;
pc = code_sect + get_unaligned_be32 (
& p [ proc_table +
( 13 * i ) + 9 ] ) ;
if ( ( pc < code_sect ) | |
( pc > = debug_sect ) )
status = - ERANGE ;
}
} else
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
pc = stack [ - - stack_ptr ] + code_sect ;
if ( ( pc < = code_sect ) | |
( pc > = debug_sect ) )
status = - ERANGE ;
}
break ;
case OP_CMPS :
/*
* Array short compare
* . . . stack 0 is source 1 value
* . . . stack 1 is source 2 value
* . . . stack 2 is mask value
* . . . stack 3 is count
*/
if ( altera_check_stack ( stack_ptr , 4 , & status ) ) {
s32 a = stack [ - - stack_ptr ] ;
s32 b = stack [ - - stack_ptr ] ;
long_tmp = stack [ - - stack_ptr ] ;
count = stack [ stack_ptr - 1 ] ;
if ( ( count < 1 ) | | ( count > 32 ) )
status = - ERANGE ;
else {
long_tmp & = ( ( - 1L ) > > ( 32 - count ) ) ;
stack [ stack_ptr - 1 ] =
( ( a & long_tmp ) = = ( b & long_tmp ) )
? 1L : 0L ;
}
}
break ;
case OP_PINT :
/*
* PRINT add integer
* . . . stack 0 is integer value
*/
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
sprintf ( & msg_buff [ strlen ( msg_buff ) ] ,
" %ld " , stack [ - - stack_ptr ] ) ;
break ;
case OP_PRNT :
/* PRINT finish */
if ( debug )
printk ( msg_buff , " \n " ) ;
msg_buff [ 0 ] = ' \0 ' ;
break ;
case OP_DSS :
/*
* DRSCAN short
* . . . stack 0 is scan data
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_tmp = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_drscan ( astate , count , charbuf , 0 ) ;
break ;
case OP_DSSC :
/*
* DRSCAN short with capture
* . . . stack 0 is scan data
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_tmp = stack [ - - stack_ptr ] ;
count = stack [ stack_ptr - 1 ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_swap_dr ( astate , count , charbuf ,
0 , charbuf , 0 ) ;
stack [ stack_ptr - 1 ] = get_unaligned_le32 ( & charbuf [ 0 ] ) ;
break ;
case OP_ISS :
/*
* IRSCAN short
* . . . stack 0 is scan data
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_tmp = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_irscan ( astate , count , charbuf , 0 ) ;
break ;
case OP_ISSC :
/*
* IRSCAN short with capture
* . . . stack 0 is scan data
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_tmp = stack [ - - stack_ptr ] ;
count = stack [ stack_ptr - 1 ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_swap_ir ( astate , count , charbuf ,
0 , charbuf , 0 ) ;
stack [ stack_ptr - 1 ] = get_unaligned_le32 ( & charbuf [ 0 ] ) ;
break ;
case OP_DPR :
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
count = stack [ - - stack_ptr ] ;
status = altera_set_dr_pre ( & astate - > js , count , 0 , NULL ) ;
break ;
case OP_DPRL :
/*
* DRPRE with literal data
* . . . stack 0 is count
* . . . stack 1 is literal data
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
count = stack [ - - stack_ptr ] ;
long_tmp = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_set_dr_pre ( & astate - > js , count , 0 ,
charbuf ) ;
break ;
case OP_DPO :
/*
* DRPOST
* . . . stack 0 is count
*/
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
count = stack [ - - stack_ptr ] ;
status = altera_set_dr_post ( & astate - > js , count ,
0 , NULL ) ;
}
break ;
case OP_DPOL :
/*
* DRPOST with literal data
* . . . stack 0 is count
* . . . stack 1 is literal data
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
count = stack [ - - stack_ptr ] ;
long_tmp = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_set_dr_post ( & astate - > js , count , 0 ,
charbuf ) ;
break ;
case OP_IPR :
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
count = stack [ - - stack_ptr ] ;
status = altera_set_ir_pre ( & astate - > js , count ,
0 , NULL ) ;
}
break ;
case OP_IPRL :
/*
* IRPRE with literal data
* . . . stack 0 is count
* . . . stack 1 is literal data
*/
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
count = stack [ - - stack_ptr ] ;
long_tmp = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_set_ir_pre ( & astate - > js , count ,
0 , charbuf ) ;
}
break ;
case OP_IPO :
/*
* IRPOST
* . . . stack 0 is count
*/
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
count = stack [ - - stack_ptr ] ;
status = altera_set_ir_post ( & astate - > js , count ,
0 , NULL ) ;
}
break ;
case OP_IPOL :
/*
* IRPOST with literal data
* . . . stack 0 is count
* . . . stack 1 is literal data
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
count = stack [ - - stack_ptr ] ;
long_tmp = stack [ - - stack_ptr ] ;
put_unaligned_le32 ( long_tmp , & charbuf [ 0 ] ) ;
status = altera_set_ir_post ( & astate - > js , count , 0 ,
charbuf ) ;
break ;
case OP_PCHR :
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
u8 ch ;
count = strlen ( msg_buff ) ;
ch = ( char ) stack [ - - stack_ptr ] ;
if ( ( ch < 1 ) | | ( ch > 127 ) ) {
/*
* character code out of range
* instead of flagging an error ,
* force the value to 127
*/
ch = 127 ;
}
msg_buff [ count ] = ch ;
msg_buff [ count + 1 ] = ' \0 ' ;
}
break ;
case OP_EXIT :
if ( altera_check_stack ( stack_ptr , 1 , & status ) )
* exit_code = stack [ - - stack_ptr ] ;
done = 1 ;
break ;
case OP_EQU :
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
- - stack_ptr ;
stack [ stack_ptr - 1 ] =
( stack [ stack_ptr - 1 ] = = stack [ stack_ptr ] ) ?
1L : 0L ;
break ;
case OP_POPT :
if ( altera_check_stack ( stack_ptr , 1 , & status ) )
- - stack_ptr ;
break ;
case OP_ABS :
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
if ( stack [ stack_ptr - 1 ] < 0 )
stack [ stack_ptr - 1 ] = 0 - stack [ stack_ptr - 1 ] ;
break ;
case OP_BCH0 :
/*
* Batch operation 0
* SWP
* SWPN 7
* SWP
* SWPN 6
* DUPN 8
* SWPN 2
* SWP
* DUPN 6
* DUPN 6
*/
/* SWP */
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
long_tmp = stack [ stack_ptr - 2 ] ;
stack [ stack_ptr - 2 ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* SWPN 7 */
index = 7 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
long_tmp = stack [ stack_ptr - index ] ;
stack [ stack_ptr - index ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* SWP */
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
long_tmp = stack [ stack_ptr - 2 ] ;
stack [ stack_ptr - 2 ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* SWPN 6 */
index = 6 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
long_tmp = stack [ stack_ptr - index ] ;
stack [ stack_ptr - index ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* DUPN 8 */
index = 8 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
stack [ stack_ptr ] = stack [ stack_ptr - index ] ;
+ + stack_ptr ;
}
/* SWPN 2 */
index = 2 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
long_tmp = stack [ stack_ptr - index ] ;
stack [ stack_ptr - index ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* SWP */
if ( altera_check_stack ( stack_ptr , 2 , & status ) ) {
long_tmp = stack [ stack_ptr - 2 ] ;
stack [ stack_ptr - 2 ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
/* DUPN 6 */
index = 6 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
stack [ stack_ptr ] = stack [ stack_ptr - index ] ;
+ + stack_ptr ;
}
/* DUPN 6 */
index = 6 + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
stack [ stack_ptr ] = stack [ stack_ptr - index ] ;
+ + stack_ptr ;
}
break ;
case OP_PSH0 :
stack [ stack_ptr + + ] = 0 ;
break ;
case OP_PSHL :
stack [ stack_ptr + + ] = ( s32 ) args [ 0 ] ;
break ;
case OP_PSHV :
stack [ stack_ptr + + ] = vars [ args [ 0 ] ] ;
break ;
case OP_JMP :
pc = args [ 0 ] + code_sect ;
if ( ( pc < code_sect ) | | ( pc > = debug_sect ) )
status = - ERANGE ;
break ;
case OP_CALL :
stack [ stack_ptr + + ] = pc ;
pc = args [ 0 ] + code_sect ;
if ( ( pc < code_sect ) | | ( pc > = debug_sect ) )
status = - ERANGE ;
break ;
case OP_NEXT :
/*
* Process FOR / NEXT loop
* . . . argument 0 is variable ID
* . . . stack 0 is step value
* . . . stack 1 is end value
* . . . stack 2 is top address
*/
if ( altera_check_stack ( stack_ptr , 3 , & status ) ) {
s32 step = stack [ stack_ptr - 1 ] ;
s32 end = stack [ stack_ptr - 2 ] ;
s32 top = stack [ stack_ptr - 3 ] ;
s32 iterator = vars [ args [ 0 ] ] ;
int break_out = 0 ;
if ( step < 0 ) {
if ( iterator < = end )
break_out = 1 ;
} else if ( iterator > = end )
break_out = 1 ;
if ( break_out ) {
stack_ptr - = 3 ;
} else {
vars [ args [ 0 ] ] = iterator + step ;
pc = top + code_sect ;
if ( ( pc < code_sect ) | |
( pc > = debug_sect ) )
status = - ERANGE ;
}
}
break ;
case OP_PSTR :
/*
* PRINT add string
* . . . argument 0 is string ID
*/
count = strlen ( msg_buff ) ;
strlcpy ( & msg_buff [ count ] ,
& p [ str_table + args [ 0 ] ] ,
ALTERA_MESSAGE_LENGTH - count ) ;
break ;
case OP_SINT :
/*
* STATE intermediate state
* . . . argument 0 is state code
*/
status = altera_goto_jstate ( astate , args [ 0 ] ) ;
break ;
case OP_ST :
/*
* STATE final state
* . . . argument 0 is state code
*/
status = altera_goto_jstate ( astate , args [ 0 ] ) ;
break ;
case OP_ISTP :
/*
* IRSTOP state
* . . . argument 0 is state code
*/
status = altera_set_irstop ( & astate - > js , args [ 0 ] ) ;
break ;
case OP_DSTP :
/*
* DRSTOP state
* . . . argument 0 is state code
*/
status = altera_set_drstop ( & astate - > js , args [ 0 ] ) ;
break ;
case OP_SWPN :
/*
* Exchange top with Nth stack value
* . . . argument 0 is 0 - based stack entry
* to swap with top element
*/
index = ( args [ 0 ] ) + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
long_tmp = stack [ stack_ptr - index ] ;
stack [ stack_ptr - index ] = stack [ stack_ptr - 1 ] ;
stack [ stack_ptr - 1 ] = long_tmp ;
}
break ;
case OP_DUPN :
/*
* Duplicate Nth stack value
* . . . argument 0 is 0 - based stack entry to duplicate
*/
index = ( args [ 0 ] ) + 1 ;
if ( altera_check_stack ( stack_ptr , index , & status ) ) {
stack [ stack_ptr ] = stack [ stack_ptr - index ] ;
+ + stack_ptr ;
}
break ;
case OP_POPV :
/*
* Pop stack into scalar variable
* . . . argument 0 is variable ID
* . . . stack 0 is value
*/
if ( altera_check_stack ( stack_ptr , 1 , & status ) )
vars [ args [ 0 ] ] = stack [ - - stack_ptr ] ;
break ;
case OP_POPE :
/*
* Pop stack into integer array element
* . . . argument 0 is variable ID
* . . . stack 0 is array index
* . . . stack 1 is value
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
variable_id = args [ 0 ] ;
/*
* If variable is read - only ,
* convert to writable array
*/
if ( ( version > 0 ) & &
( ( attrs [ variable_id ] & 0x9c ) = = 0x1c ) ) {
/* Allocate a writable buffer for this array */
count = var_size [ variable_id ] ;
long_tmp = vars [ variable_id ] ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
longptr_tmp = kcalloc ( count , sizeof ( long ) ,
2011-01-25 17:00:00 -03:00
GFP_KERNEL ) ;
vars [ variable_id ] = ( long ) longptr_tmp ;
if ( vars [ variable_id ] = = 0 ) {
status = - ENOMEM ;
break ;
}
/* copy previous contents into buffer */
for ( i = 0 ; i < count ; + + i ) {
longptr_tmp [ i ] =
get_unaligned_be32 ( & p [ long_tmp ] ) ;
long_tmp + = sizeof ( long ) ;
}
/*
* set bit 7 - buffer was
* dynamically allocated
*/
attrs [ variable_id ] | = 0x80 ;
/* clear bit 2 - variable is writable */
attrs [ variable_id ] & = ~ 0x04 ;
attrs [ variable_id ] | = 0x01 ;
}
/* check that variable is a writable integer array */
if ( ( attrs [ variable_id ] & 0x1c ) ! = 0x18 )
status = - ERANGE ;
else {
longptr_tmp = ( long * ) vars [ variable_id ] ;
/* pop the array index */
index = stack [ - - stack_ptr ] ;
/* pop the value and store it into the array */
longptr_tmp [ index ] = stack [ - - stack_ptr ] ;
}
break ;
case OP_POPA :
/*
* Pop stack into Boolean array
* . . . argument 0 is variable ID
* . . . stack 0 is count
* . . . stack 1 is array index
* . . . stack 2 is value
*/
if ( ! altera_check_stack ( stack_ptr , 3 , & status ) )
break ;
variable_id = args [ 0 ] ;
/*
* If variable is read - only ,
* convert to writable array
*/
if ( ( version > 0 ) & &
( ( attrs [ variable_id ] & 0x9c ) = = 0x0c ) ) {
/* Allocate a writable buffer for this array */
long_tmp =
( var_size [ variable_id ] + 7L ) > > 3L ;
charptr_tmp2 = ( u8 * ) vars [ variable_id ] ;
charptr_tmp =
kzalloc ( long_tmp , GFP_KERNEL ) ;
vars [ variable_id ] = ( long ) charptr_tmp ;
if ( vars [ variable_id ] = = 0 ) {
status = - ENOMEM ;
break ;
}
/* zero the buffer */
for ( long_idx = 0L ;
long_idx < long_tmp ;
+ + long_idx ) {
charptr_tmp [ long_idx ] = 0 ;
}
/* copy previous contents into buffer */
for ( long_idx = 0L ;
long_idx < var_size [ variable_id ] ;
+ + long_idx ) {
long_idx2 = long_idx ;
if ( charptr_tmp2 [ long_idx2 > > 3 ] &
( 1 < < ( long_idx2 & 7 ) ) ) {
charptr_tmp [ long_idx > > 3 ] | =
( 1 < < ( long_idx & 7 ) ) ;
}
}
/*
* set bit 7 - buffer was
* dynamically allocated
*/
attrs [ variable_id ] | = 0x80 ;
/* clear bit 2 - variable is writable */
attrs [ variable_id ] & = ~ 0x04 ;
attrs [ variable_id ] | = 0x01 ;
}
/*
* check that variable is
* a writable Boolean array
*/
if ( ( attrs [ variable_id ] & 0x1c ) ! = 0x08 ) {
status = - ERANGE ;
break ;
}
charptr_tmp = ( u8 * ) vars [ variable_id ] ;
/* pop the count (number of bits to copy) */
long_count = stack [ - - stack_ptr ] ;
/* pop the array index */
long_idx = stack [ - - stack_ptr ] ;
reverse = 0 ;
if ( version > 0 ) {
/*
* stack 0 = array right index
* stack 1 = array left index
*/
if ( long_idx > long_count ) {
reverse = 1 ;
long_tmp = long_count ;
long_count = 1 + long_idx -
long_count ;
long_idx = long_tmp ;
/* reverse POPA is not supported */
status = - ERANGE ;
break ;
} else
long_count = 1 + long_count -
long_idx ;
}
/* pop the data */
long_tmp = stack [ - - stack_ptr ] ;
if ( long_count < 1 ) {
status = - ERANGE ;
break ;
}
for ( i = 0 ; i < long_count ; + + i ) {
if ( long_tmp & ( 1L < < ( s32 ) i ) )
charptr_tmp [ long_idx > > 3L ] | =
( 1L < < ( long_idx & 7L ) ) ;
else
charptr_tmp [ long_idx > > 3L ] & =
~ ( 1L < < ( long_idx & 7L ) ) ;
+ + long_idx ;
}
break ;
case OP_JMPZ :
/*
* Pop stack and branch if zero
* . . . argument 0 is address
* . . . stack 0 is condition value
*/
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
if ( stack [ - - stack_ptr ] = = 0 ) {
pc = args [ 0 ] + code_sect ;
if ( ( pc < code_sect ) | |
( pc > = debug_sect ) )
status = - ERANGE ;
}
}
break ;
case OP_DS :
case OP_IS :
/*
* DRSCAN
* IRSCAN
* . . . argument 0 is scan data variable ID
* . . . stack 0 is array index
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_idx = stack [ - - stack_ptr ] ;
long_count = stack [ - - stack_ptr ] ;
reverse = 0 ;
if ( version > 0 ) {
/*
* stack 0 = array right index
* stack 1 = array left index
* stack 2 = count
*/
long_tmp = long_count ;
long_count = stack [ - - stack_ptr ] ;
if ( long_idx > long_tmp ) {
reverse = 1 ;
long_idx = long_tmp ;
}
}
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
if ( reverse ) {
/*
* allocate a buffer
* and reverse the data order
*/
charptr_tmp2 = charptr_tmp ;
charptr_tmp = kzalloc ( ( long_count > > 3 ) + 1 ,
GFP_KERNEL ) ;
if ( charptr_tmp = = NULL ) {
status = - ENOMEM ;
break ;
}
long_tmp = long_idx + long_count - 1 ;
long_idx2 = 0 ;
while ( long_idx2 < long_count ) {
if ( charptr_tmp2 [ long_tmp > > 3 ] &
( 1 < < ( long_tmp & 7 ) ) )
charptr_tmp [ long_idx2 > > 3 ] | =
( 1 < < ( long_idx2 & 7 ) ) ;
else
charptr_tmp [ long_idx2 > > 3 ] & =
~ ( 1 < < ( long_idx2 & 7 ) ) ;
- - long_tmp ;
+ + long_idx2 ;
}
}
if ( opcode = = 0x51 ) /* DS */
status = altera_drscan ( astate , long_count ,
charptr_tmp , long_idx ) ;
else /* IS */
status = altera_irscan ( astate , long_count ,
charptr_tmp , long_idx ) ;
if ( reverse )
kfree ( charptr_tmp ) ;
break ;
case OP_DPRA :
/*
* DRPRE with array data
* . . . argument 0 is variable ID
* . . . stack 0 is array index
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
index = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
if ( version > 0 )
/*
* stack 0 = array right index
* stack 1 = array left index
*/
count = 1 + count - index ;
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
status = altera_set_dr_pre ( & astate - > js , count , index ,
charptr_tmp ) ;
break ;
case OP_DPOA :
/*
* DRPOST with array data
* . . . argument 0 is variable ID
* . . . stack 0 is array index
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
index = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
if ( version > 0 )
/*
* stack 0 = array right index
* stack 1 = array left index
*/
count = 1 + count - index ;
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
status = altera_set_dr_post ( & astate - > js , count , index ,
charptr_tmp ) ;
break ;
case OP_IPRA :
/*
* IRPRE with array data
* . . . argument 0 is variable ID
* . . . stack 0 is array index
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
index = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
if ( version > 0 )
/*
* stack 0 = array right index
* stack 1 = array left index
*/
count = 1 + count - index ;
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
status = altera_set_ir_pre ( & astate - > js , count , index ,
charptr_tmp ) ;
break ;
case OP_IPOA :
/*
* IRPOST with array data
* . . . argument 0 is variable ID
* . . . stack 0 is array index
* . . . stack 1 is count
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
index = stack [ - - stack_ptr ] ;
count = stack [ - - stack_ptr ] ;
if ( version > 0 )
/*
* stack 0 = array right index
* stack 1 = array left index
*/
count = 1 + count - index ;
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
status = altera_set_ir_post ( & astate - > js , count , index ,
charptr_tmp ) ;
break ;
case OP_EXPT :
/*
* EXPORT
* . . . argument 0 is string ID
* . . . stack 0 is integer expression
*/
if ( altera_check_stack ( stack_ptr , 1 , & status ) ) {
name = & p [ str_table + args [ 0 ] ] ;
long_tmp = stack [ - - stack_ptr ] ;
altera_export_int ( name , long_tmp ) ;
}
break ;
case OP_PSHE :
/*
* Push integer array element
* . . . argument 0 is variable ID
* . . . stack 0 is array index
*/
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
variable_id = args [ 0 ] ;
index = stack [ stack_ptr - 1 ] ;
/* check variable type */
if ( ( attrs [ variable_id ] & 0x1f ) = = 0x19 ) {
/* writable integer array */
longptr_tmp = ( long * ) vars [ variable_id ] ;
stack [ stack_ptr - 1 ] = longptr_tmp [ index ] ;
} else if ( ( attrs [ variable_id ] & 0x1f ) = = 0x1c ) {
/* read-only integer array */
long_tmp = vars [ variable_id ] +
( index * sizeof ( long ) ) ;
stack [ stack_ptr - 1 ] =
get_unaligned_be32 ( & p [ long_tmp ] ) ;
} else
status = - ERANGE ;
break ;
case OP_PSHA :
/*
* Push Boolean array
* . . . argument 0 is variable ID
* . . . stack 0 is count
* . . . stack 1 is array index
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
variable_id = args [ 0 ] ;
/* check that variable is a Boolean array */
if ( ( attrs [ variable_id ] & 0x18 ) ! = 0x08 ) {
status = - ERANGE ;
break ;
}
charptr_tmp = ( u8 * ) vars [ variable_id ] ;
/* pop the count (number of bits to copy) */
count = stack [ - - stack_ptr ] ;
/* pop the array index */
index = stack [ stack_ptr - 1 ] ;
if ( version > 0 )
/*
* stack 0 = array right index
* stack 1 = array left index
*/
count = 1 + count - index ;
if ( ( count < 1 ) | | ( count > 32 ) ) {
status = - ERANGE ;
break ;
}
long_tmp = 0L ;
for ( i = 0 ; i < count ; + + i )
if ( charptr_tmp [ ( i + index ) > > 3 ] &
( 1 < < ( ( i + index ) & 7 ) ) )
long_tmp | = ( 1L < < i ) ;
stack [ stack_ptr - 1 ] = long_tmp ;
break ;
case OP_DYNA :
/*
* Dynamically change size of array
* . . . argument 0 is variable ID
* . . . stack 0 is new size
*/
if ( ! altera_check_stack ( stack_ptr , 1 , & status ) )
break ;
variable_id = args [ 0 ] ;
long_tmp = stack [ - - stack_ptr ] ;
if ( long_tmp > var_size [ variable_id ] ) {
var_size [ variable_id ] = long_tmp ;
if ( attrs [ variable_id ] & 0x10 )
/* allocate integer array */
long_tmp * = sizeof ( long ) ;
else
/* allocate Boolean array */
long_tmp = ( long_tmp + 7 ) > > 3 ;
/*
* If the buffer was previously allocated ,
* free it
*/
if ( attrs [ variable_id ] & 0x80 ) {
kfree ( ( void * ) vars [ variable_id ] ) ;
vars [ variable_id ] = 0 ;
}
/*
* Allocate a new buffer
* of the requested size
*/
vars [ variable_id ] = ( long )
kzalloc ( long_tmp , GFP_KERNEL ) ;
if ( vars [ variable_id ] = = 0 ) {
status = - ENOMEM ;
break ;
}
/*
* Set the attribute bit to indicate that
* this buffer was dynamically allocated and
* should be freed later
*/
attrs [ variable_id ] | = 0x80 ;
/* zero out memory */
count = ( ( var_size [ variable_id ] + 7L ) /
8L ) ;
charptr_tmp = ( u8 * ) ( vars [ variable_id ] ) ;
for ( index = 0 ; index < count ; + + index )
charptr_tmp [ index ] = 0 ;
}
break ;
case OP_EXPV :
/*
* Export Boolean array
* . . . argument 0 is string ID
* . . . stack 0 is variable ID
* . . . stack 1 is array right index
* . . . stack 2 is array left index
*/
if ( ! altera_check_stack ( stack_ptr , 3 , & status ) )
break ;
if ( version = = 0 ) {
/* EXPV is not supported in JBC 1.0 */
bad_opcode = 1 ;
break ;
}
name = & p [ str_table + args [ 0 ] ] ;
variable_id = stack [ - - stack_ptr ] ;
long_idx = stack [ - - stack_ptr ] ; /* right indx */
long_idx2 = stack [ - - stack_ptr ] ; /* left indx */
if ( long_idx > long_idx2 ) {
/* reverse indices not supported */
status = - ERANGE ;
break ;
}
long_count = 1 + long_idx2 - long_idx ;
charptr_tmp = ( u8 * ) vars [ variable_id ] ;
charptr_tmp2 = NULL ;
if ( ( long_idx & 7L ) ! = 0 ) {
s32 k = long_idx ;
charptr_tmp2 =
kzalloc ( ( ( long_count + 7L ) / 8L ) ,
GFP_KERNEL ) ;
if ( charptr_tmp2 = = NULL ) {
status = - ENOMEM ;
break ;
}
for ( i = 0 ; i < long_count ; + + i ) {
if ( charptr_tmp [ k > > 3 ] &
( 1 < < ( k & 7 ) ) )
charptr_tmp2 [ i > > 3 ] | =
( 1 < < ( i & 7 ) ) ;
else
charptr_tmp2 [ i > > 3 ] & =
~ ( 1 < < ( i & 7 ) ) ;
+ + k ;
}
charptr_tmp = charptr_tmp2 ;
} else if ( long_idx ! = 0 )
charptr_tmp = & charptr_tmp [ long_idx > > 3 ] ;
altera_export_bool_array ( name , charptr_tmp ,
long_count ) ;
/* free allocated buffer */
if ( ( long_idx & 7L ) ! = 0 )
kfree ( charptr_tmp2 ) ;
break ;
case OP_COPY : {
/*
* Array copy
* . . . argument 0 is dest ID
* . . . argument 1 is source ID
* . . . stack 0 is count
* . . . stack 1 is dest index
* . . . stack 2 is source index
*/
s32 copy_count ;
s32 copy_index ;
s32 copy_index2 ;
s32 destleft ;
s32 src_count ;
s32 dest_count ;
int src_reverse = 0 ;
int dest_reverse = 0 ;
if ( ! altera_check_stack ( stack_ptr , 3 , & status ) )
break ;
copy_count = stack [ - - stack_ptr ] ;
copy_index = stack [ - - stack_ptr ] ;
copy_index2 = stack [ - - stack_ptr ] ;
reverse = 0 ;
if ( version > 0 ) {
/*
* stack 0 = source right index
* stack 1 = source left index
* stack 2 = destination right index
* stack 3 = destination left index
*/
destleft = stack [ - - stack_ptr ] ;
if ( copy_count > copy_index ) {
src_reverse = 1 ;
reverse = 1 ;
src_count = 1 + copy_count - copy_index ;
/* copy_index = source start index */
} else {
src_count = 1 + copy_index - copy_count ;
/* source start index */
copy_index = copy_count ;
}
if ( copy_index2 > destleft ) {
dest_reverse = 1 ;
reverse = ! reverse ;
dest_count = 1 + copy_index2 - destleft ;
/* destination start index */
copy_index2 = destleft ;
} else
dest_count = 1 + destleft - copy_index2 ;
copy_count = ( src_count < dest_count ) ?
src_count : dest_count ;
if ( ( src_reverse | | dest_reverse ) & &
( src_count ! = dest_count ) )
/*
* If either the source or destination
* is reversed , we can ' t tolerate
* a length mismatch , because we
* " left justify " arrays when copying .
* This won ' t work correctly
* with reversed arrays .
*/
status = - ERANGE ;
}
count = copy_count ;
index = copy_index ;
index2 = copy_index2 ;
/*
* If destination is a read - only array ,
* allocate a buffer and convert it to a writable array
*/
variable_id = args [ 1 ] ;
if ( ( version > 0 ) & &
( ( attrs [ variable_id ] & 0x9c ) = = 0x0c ) ) {
/* Allocate a writable buffer for this array */
long_tmp =
( var_size [ variable_id ] + 7L ) > > 3L ;
charptr_tmp2 = ( u8 * ) vars [ variable_id ] ;
charptr_tmp =
kzalloc ( long_tmp , GFP_KERNEL ) ;
vars [ variable_id ] = ( long ) charptr_tmp ;
if ( vars [ variable_id ] = = 0 ) {
status = - ENOMEM ;
break ;
}
/* zero the buffer */
for ( long_idx = 0L ; long_idx < long_tmp ;
+ + long_idx )
charptr_tmp [ long_idx ] = 0 ;
/* copy previous contents into buffer */
for ( long_idx = 0L ;
long_idx < var_size [ variable_id ] ;
+ + long_idx ) {
long_idx2 = long_idx ;
if ( charptr_tmp2 [ long_idx2 > > 3 ] &
( 1 < < ( long_idx2 & 7 ) ) )
charptr_tmp [ long_idx > > 3 ] | =
( 1 < < ( long_idx & 7 ) ) ;
}
/*
set bit 7 - buffer was dynamically allocated */
attrs [ variable_id ] | = 0x80 ;
/* clear bit 2 - variable is writable */
attrs [ variable_id ] & = ~ 0x04 ;
attrs [ variable_id ] | = 0x01 ;
}
charptr_tmp = ( u8 * ) vars [ args [ 1 ] ] ;
charptr_tmp2 = ( u8 * ) vars [ args [ 0 ] ] ;
/* check if destination is a writable Boolean array */
if ( ( attrs [ args [ 1 ] ] & 0x1c ) ! = 0x08 ) {
status = - ERANGE ;
break ;
}
if ( count < 1 ) {
status = - ERANGE ;
break ;
}
if ( reverse )
index2 + = ( count - 1 ) ;
for ( i = 0 ; i < count ; + + i ) {
if ( charptr_tmp2 [ index > > 3 ] &
( 1 < < ( index & 7 ) ) )
charptr_tmp [ index2 > > 3 ] | =
( 1 < < ( index2 & 7 ) ) ;
else
charptr_tmp [ index2 > > 3 ] & =
~ ( 1 < < ( index2 & 7 ) ) ;
+ + index ;
if ( reverse )
- - index2 ;
else
+ + index2 ;
}
break ;
}
case OP_DSC :
case OP_ISC : {
/*
* DRSCAN with capture
* IRSCAN with capture
* . . . argument 0 is scan data variable ID
* . . . argument 1 is capture variable ID
* . . . stack 0 is capture index
* . . . stack 1 is scan data index
* . . . stack 2 is count
*/
s32 scan_right , scan_left ;
s32 capture_count = 0 ;
s32 scan_count = 0 ;
s32 capture_index ;
s32 scan_index ;
if ( ! altera_check_stack ( stack_ptr , 3 , & status ) )
break ;
capture_index = stack [ - - stack_ptr ] ;
scan_index = stack [ - - stack_ptr ] ;
if ( version > 0 ) {
/*
* stack 0 = capture right index
* stack 1 = capture left index
* stack 2 = scan right index
* stack 3 = scan left index
* stack 4 = count
*/
scan_right = stack [ - - stack_ptr ] ;
scan_left = stack [ - - stack_ptr ] ;
capture_count = 1 + scan_index - capture_index ;
scan_count = 1 + scan_left - scan_right ;
scan_index = scan_right ;
}
long_count = stack [ - - stack_ptr ] ;
/*
* If capture array is read - only , allocate a buffer
* and convert it to a writable array
*/
variable_id = args [ 1 ] ;
if ( ( version > 0 ) & &
( ( attrs [ variable_id ] & 0x9c ) = = 0x0c ) ) {
/* Allocate a writable buffer for this array */
long_tmp =
( var_size [ variable_id ] + 7L ) > > 3L ;
charptr_tmp2 = ( u8 * ) vars [ variable_id ] ;
charptr_tmp =
kzalloc ( long_tmp , GFP_KERNEL ) ;
vars [ variable_id ] = ( long ) charptr_tmp ;
if ( vars [ variable_id ] = = 0 ) {
status = - ENOMEM ;
break ;
}
/* zero the buffer */
for ( long_idx = 0L ; long_idx < long_tmp ;
+ + long_idx )
charptr_tmp [ long_idx ] = 0 ;
/* copy previous contents into buffer */
for ( long_idx = 0L ;
long_idx < var_size [ variable_id ] ;
+ + long_idx ) {
long_idx2 = long_idx ;
if ( charptr_tmp2 [ long_idx2 > > 3 ] &
( 1 < < ( long_idx2 & 7 ) ) )
charptr_tmp [ long_idx > > 3 ] | =
( 1 < < ( long_idx & 7 ) ) ;
}
/*
* set bit 7 - buffer was
* dynamically allocated
*/
attrs [ variable_id ] | = 0x80 ;
/* clear bit 2 - variable is writable */
attrs [ variable_id ] & = ~ 0x04 ;
attrs [ variable_id ] | = 0x01 ;
}
charptr_tmp = ( u8 * ) vars [ args [ 0 ] ] ;
charptr_tmp2 = ( u8 * ) vars [ args [ 1 ] ] ;
if ( ( version > 0 ) & &
( ( long_count > capture_count ) | |
( long_count > scan_count ) ) ) {
status = - ERANGE ;
break ;
}
/*
* check that capture array
* is a writable Boolean array
*/
if ( ( attrs [ args [ 1 ] ] & 0x1c ) ! = 0x08 ) {
status = - ERANGE ;
break ;
}
if ( status = = 0 ) {
if ( opcode = = 0x82 ) /* DSC */
status = altera_swap_dr ( astate ,
long_count ,
charptr_tmp ,
scan_index ,
charptr_tmp2 ,
capture_index ) ;
else /* ISC */
status = altera_swap_ir ( astate ,
long_count ,
charptr_tmp ,
scan_index ,
charptr_tmp2 ,
capture_index ) ;
}
break ;
}
case OP_WAIT :
/*
* WAIT
* . . . argument 0 is wait state
* . . . argument 1 is end state
* . . . stack 0 is cycles
* . . . stack 1 is microseconds
*/
if ( ! altera_check_stack ( stack_ptr , 2 , & status ) )
break ;
long_tmp = stack [ - - stack_ptr ] ;
if ( long_tmp ! = 0L )
status = altera_wait_cycles ( astate , long_tmp ,
args [ 0 ] ) ;
long_tmp = stack [ - - stack_ptr ] ;
if ( ( status = = 0 ) & & ( long_tmp ! = 0L ) )
status = altera_wait_msecs ( astate ,
long_tmp ,
args [ 0 ] ) ;
if ( ( status = = 0 ) & & ( args [ 1 ] ! = args [ 0 ] ) )
status = altera_goto_jstate ( astate ,
args [ 1 ] ) ;
if ( version > 0 ) {
- - stack_ptr ; /* throw away MAX cycles */
- - stack_ptr ; /* throw away MAX microseconds */
}
break ;
case OP_CMPA : {
/*
* Array compare
* . . . argument 0 is source 1 ID
* . . . argument 1 is source 2 ID
* . . . argument 2 is mask ID
* . . . stack 0 is source 1 index
* . . . stack 1 is source 2 index
* . . . stack 2 is mask index
* . . . stack 3 is count
*/
s32 a , b ;
u8 * source1 = ( u8 * ) vars [ args [ 0 ] ] ;
u8 * source2 = ( u8 * ) vars [ args [ 1 ] ] ;
u8 * mask = ( u8 * ) vars [ args [ 2 ] ] ;
u32 index1 ;
u32 index2 ;
u32 mask_index ;
if ( ! altera_check_stack ( stack_ptr , 4 , & status ) )
break ;
index1 = stack [ - - stack_ptr ] ;
index2 = stack [ - - stack_ptr ] ;
mask_index = stack [ - - stack_ptr ] ;
long_count = stack [ - - stack_ptr ] ;
if ( version > 0 ) {
/*
* stack 0 = source 1 right index
* stack 1 = source 1 left index
* stack 2 = source 2 right index
* stack 3 = source 2 left index
* stack 4 = mask right index
* stack 5 = mask left index
*/
s32 mask_right = stack [ - - stack_ptr ] ;
s32 mask_left = stack [ - - stack_ptr ] ;
/* source 1 count */
a = 1 + index2 - index1 ;
/* source 2 count */
b = 1 + long_count - mask_index ;
a = ( a < b ) ? a : b ;
/* mask count */
b = 1 + mask_left - mask_right ;
a = ( a < b ) ? a : b ;
/* source 2 start index */
index2 = mask_index ;
/* mask start index */
mask_index = mask_right ;
long_count = a ;
}
long_tmp = 1L ;
if ( long_count < 1 )
status = - ERANGE ;
else {
count = long_count ;
for ( i = 0 ; i < count ; + + i ) {
if ( mask [ mask_index > > 3 ] &
( 1 < < ( mask_index & 7 ) ) ) {
a = source1 [ index1 > > 3 ] &
( 1 < < ( index1 & 7 ) )
? 1 : 0 ;
b = source2 [ index2 > > 3 ] &
( 1 < < ( index2 & 7 ) )
? 1 : 0 ;
if ( a ! = b ) /* failure */
long_tmp = 0L ;
}
+ + index1 ;
+ + index2 ;
+ + mask_index ;
}
}
stack [ stack_ptr + + ] = long_tmp ;
break ;
}
default :
/* Unrecognized opcode -- ERROR! */
bad_opcode = 1 ;
break ;
}
if ( bad_opcode )
status = - ENOSYS ;
if ( ( stack_ptr < 0 ) | | ( stack_ptr > = ALTERA_STACK_SIZE ) )
status = - EOVERFLOW ;
if ( status ! = 0 ) {
done = 1 ;
* error_address = ( s32 ) ( opcode_address - code_sect ) ;
}
}
altera_free_buffers ( astate ) ;
/* Free all dynamically allocated arrays */
if ( ( attrs ! = NULL ) & & ( vars ! = NULL ) )
for ( i = 0 ; i < sym_count ; + + i )
if ( attrs [ i ] & 0x80 )
kfree ( ( void * ) vars [ i ] ) ;
kfree ( vars ) ;
kfree ( var_size ) ;
kfree ( attrs ) ;
kfree ( proc_attributes ) ;
return status ;
}
altera-stapl: altera_get_note: prevent write beyond end of 'key'
altera_get_note is called from altera_init, where key is kzalloc(33).
When the allocation functions are annotated to allow the compiler to see
the sizes of objects, and with FORTIFY_SOURCE, we see:
In file included from drivers/misc/altera-stapl/altera.c:14:0:
In function ‘strlcpy’,
inlined from ‘altera_init’ at drivers/misc/altera-stapl/altera.c:2189:5:
include/linux/string.h:378:4: error: call to ‘__write_overflow’ declared with attribute error: detected write beyond size of object passed as 1st parameter
__write_overflow();
^~~~~~~~~~~~~~~~~~
That refers to this code in altera_get_note:
if (key != NULL)
strlcpy(key, &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])],
length);
The error triggers because the length of 'key' is 33, but the copy
uses length supplied as the 'length' parameter, which is always
256. Split the size parameter into key_len and val_len, and use the
appropriate length depending on what is being copied.
Detected by compiler error, only compile-tested.
Cc: "Igor M. Liplianin" <liplianin@netup.ru>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Link: https://lore.kernel.org/r/20200120074344.504-2-dja@axtens.net
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/202002251042.D898E67AC@keescook
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-02-25 10:44:27 -08:00
static int altera_get_note ( u8 * p , s32 program_size , s32 * offset ,
char * key , char * value , int keylen , int vallen )
2011-01-25 17:00:00 -03:00
/*
* Gets key and value of NOTE fields in the JBC file .
* Can be called in two modes : if offset pointer is NULL ,
* then the function searches for note fields which match
* the key string provided . If offset is not NULL , then
* the function finds the next note field of any key ,
* starting at the offset specified by the offset pointer .
* Returns 0 for success , else appropriate error code
*/
{
int status = - ENODATA ;
u32 note_strings = 0L ;
u32 note_table = 0L ;
u32 note_count = 0L ;
u32 first_word = 0L ;
int version = 0 ;
int delta = 0 ;
char * key_ptr ;
char * value_ptr ;
int i ;
/* Read header information */
if ( program_size > 52L ) {
first_word = get_unaligned_be32 ( & p [ 0 ] ) ;
version = ( first_word & 1L ) ;
delta = version * 8 ;
note_strings = get_unaligned_be32 ( & p [ 8 + delta ] ) ;
note_table = get_unaligned_be32 ( & p [ 12 + delta ] ) ;
note_count = get_unaligned_be32 ( & p [ 44 + ( 2 * delta ) ] ) ;
}
if ( ( first_word ! = 0x4A414D00L ) & & ( first_word ! = 0x4A414D01L ) )
return - EIO ;
if ( note_count < = 0L )
return status ;
if ( offset = = NULL ) {
/*
* We will search for the first note with a specific key ,
* and return only the value
*/
for ( i = 0 ; ( i < note_count ) & &
( status ! = 0 ) ; + + i ) {
key_ptr = & p [ note_strings +
get_unaligned_be32 (
& p [ note_table + ( 8 * i ) ] ) ] ;
2018-11-24 12:34:10 +00:00
if ( key & & ! strncasecmp ( key , key_ptr , strlen ( key_ptr ) ) ) {
2011-01-25 17:00:00 -03:00
status = 0 ;
value_ptr = & p [ note_strings +
get_unaligned_be32 (
& p [ note_table + ( 8 * i ) + 4 ] ) ] ;
if ( value ! = NULL )
altera-stapl: altera_get_note: prevent write beyond end of 'key'
altera_get_note is called from altera_init, where key is kzalloc(33).
When the allocation functions are annotated to allow the compiler to see
the sizes of objects, and with FORTIFY_SOURCE, we see:
In file included from drivers/misc/altera-stapl/altera.c:14:0:
In function ‘strlcpy’,
inlined from ‘altera_init’ at drivers/misc/altera-stapl/altera.c:2189:5:
include/linux/string.h:378:4: error: call to ‘__write_overflow’ declared with attribute error: detected write beyond size of object passed as 1st parameter
__write_overflow();
^~~~~~~~~~~~~~~~~~
That refers to this code in altera_get_note:
if (key != NULL)
strlcpy(key, &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])],
length);
The error triggers because the length of 'key' is 33, but the copy
uses length supplied as the 'length' parameter, which is always
256. Split the size parameter into key_len and val_len, and use the
appropriate length depending on what is being copied.
Detected by compiler error, only compile-tested.
Cc: "Igor M. Liplianin" <liplianin@netup.ru>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Link: https://lore.kernel.org/r/20200120074344.504-2-dja@axtens.net
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/202002251042.D898E67AC@keescook
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-02-25 10:44:27 -08:00
strlcpy ( value , value_ptr , vallen ) ;
2011-01-25 17:00:00 -03:00
}
}
} else {
/*
* We will search for the next note , regardless of the key ,
* and return both the value and the key
*/
i = * offset ;
if ( ( i > = 0 ) & & ( i < note_count ) ) {
status = 0 ;
if ( key ! = NULL )
strlcpy ( key , & p [ note_strings +
get_unaligned_be32 (
& p [ note_table + ( 8 * i ) ] ) ] ,
altera-stapl: altera_get_note: prevent write beyond end of 'key'
altera_get_note is called from altera_init, where key is kzalloc(33).
When the allocation functions are annotated to allow the compiler to see
the sizes of objects, and with FORTIFY_SOURCE, we see:
In file included from drivers/misc/altera-stapl/altera.c:14:0:
In function ‘strlcpy’,
inlined from ‘altera_init’ at drivers/misc/altera-stapl/altera.c:2189:5:
include/linux/string.h:378:4: error: call to ‘__write_overflow’ declared with attribute error: detected write beyond size of object passed as 1st parameter
__write_overflow();
^~~~~~~~~~~~~~~~~~
That refers to this code in altera_get_note:
if (key != NULL)
strlcpy(key, &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])],
length);
The error triggers because the length of 'key' is 33, but the copy
uses length supplied as the 'length' parameter, which is always
256. Split the size parameter into key_len and val_len, and use the
appropriate length depending on what is being copied.
Detected by compiler error, only compile-tested.
Cc: "Igor M. Liplianin" <liplianin@netup.ru>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Link: https://lore.kernel.org/r/20200120074344.504-2-dja@axtens.net
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/202002251042.D898E67AC@keescook
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-02-25 10:44:27 -08:00
keylen ) ;
2011-01-25 17:00:00 -03:00
if ( value ! = NULL )
strlcpy ( value , & p [ note_strings +
get_unaligned_be32 (
& p [ note_table + ( 8 * i ) + 4 ] ) ] ,
altera-stapl: altera_get_note: prevent write beyond end of 'key'
altera_get_note is called from altera_init, where key is kzalloc(33).
When the allocation functions are annotated to allow the compiler to see
the sizes of objects, and with FORTIFY_SOURCE, we see:
In file included from drivers/misc/altera-stapl/altera.c:14:0:
In function ‘strlcpy’,
inlined from ‘altera_init’ at drivers/misc/altera-stapl/altera.c:2189:5:
include/linux/string.h:378:4: error: call to ‘__write_overflow’ declared with attribute error: detected write beyond size of object passed as 1st parameter
__write_overflow();
^~~~~~~~~~~~~~~~~~
That refers to this code in altera_get_note:
if (key != NULL)
strlcpy(key, &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])],
length);
The error triggers because the length of 'key' is 33, but the copy
uses length supplied as the 'length' parameter, which is always
256. Split the size parameter into key_len and val_len, and use the
appropriate length depending on what is being copied.
Detected by compiler error, only compile-tested.
Cc: "Igor M. Liplianin" <liplianin@netup.ru>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Link: https://lore.kernel.org/r/20200120074344.504-2-dja@axtens.net
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/202002251042.D898E67AC@keescook
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-02-25 10:44:27 -08:00
vallen ) ;
2011-01-25 17:00:00 -03:00
* offset = i + 1 ;
}
}
return status ;
}
static int altera_check_crc ( u8 * p , s32 program_size )
{
int status = 0 ;
u16 local_expected = 0 ,
local_actual = 0 ,
shift_reg = 0xffff ;
int bit , feedback ;
u8 databyte ;
u32 i ;
u32 crc_section = 0L ;
u32 first_word = 0L ;
int version = 0 ;
int delta = 0 ;
if ( program_size > 52L ) {
first_word = get_unaligned_be32 ( & p [ 0 ] ) ;
version = ( first_word & 1L ) ;
delta = version * 8 ;
crc_section = get_unaligned_be32 ( & p [ 32 + delta ] ) ;
}
if ( ( first_word ! = 0x4A414D00L ) & & ( first_word ! = 0x4A414D01L ) )
status = - EIO ;
if ( crc_section > = program_size )
status = - EIO ;
if ( status = = 0 ) {
local_expected = ( u16 ) get_unaligned_be16 ( & p [ crc_section ] ) ;
for ( i = 0 ; i < crc_section ; + + i ) {
databyte = p [ i ] ;
for ( bit = 0 ; bit < 8 ; bit + + ) {
feedback = ( databyte ^ shift_reg ) & 0x01 ;
shift_reg > > = 1 ;
if ( feedback )
shift_reg ^ = 0x8408 ;
databyte > > = 1 ;
}
}
local_actual = ( u16 ) ~ shift_reg ;
if ( local_expected ! = local_actual )
status = - EILSEQ ;
}
if ( debug | | status ) {
switch ( status ) {
case 0 :
printk ( KERN_INFO " %s: CRC matched: %04x \n " , __func__ ,
local_actual ) ;
break ;
case - EILSEQ :
printk ( KERN_ERR " %s: CRC mismatch: expected %04x, "
" actual %04x \n " , __func__ , local_expected ,
local_actual ) ;
break ;
case - ENODATA :
printk ( KERN_ERR " %s: expected CRC not found, "
" actual CRC = %04x \n " , __func__ ,
local_actual ) ;
break ;
case - EIO :
printk ( KERN_ERR " %s: error: format isn't "
" recognized. \n " , __func__ ) ;
break ;
default :
printk ( KERN_ERR " %s: CRC function returned error "
" code %d \n " , __func__ , status ) ;
break ;
}
}
return status ;
}
static int altera_get_file_info ( u8 * p ,
s32 program_size ,
int * format_version ,
int * action_count ,
int * procedure_count )
{
int status = - EIO ;
u32 first_word = 0 ;
int version = 0 ;
if ( program_size < = 52L )
return status ;
first_word = get_unaligned_be32 ( & p [ 0 ] ) ;
if ( ( first_word = = 0x4A414D00L ) | | ( first_word = = 0x4A414D01L ) ) {
status = 0 ;
version = ( first_word & 1L ) ;
* format_version = version + 1 ;
if ( version > 0 ) {
* action_count = get_unaligned_be32 ( & p [ 48 ] ) ;
* procedure_count = get_unaligned_be32 ( & p [ 52 ] ) ;
}
}
return status ;
}
static int altera_get_act_info ( u8 * p ,
s32 program_size ,
int index ,
char * * name ,
char * * description ,
struct altera_procinfo * * proc_list )
{
int status = - EIO ;
struct altera_procinfo * procptr = NULL ;
struct altera_procinfo * tmpptr = NULL ;
u32 first_word = 0L ;
u32 action_table = 0L ;
u32 proc_table = 0L ;
u32 str_table = 0L ;
u32 note_strings = 0L ;
u32 action_count = 0L ;
u32 proc_count = 0L ;
u32 act_name_id = 0L ;
u32 act_desc_id = 0L ;
u32 act_proc_id = 0L ;
u32 act_proc_name = 0L ;
u8 act_proc_attribute = 0 ;
if ( program_size < = 52L )
return status ;
/* Read header information */
first_word = get_unaligned_be32 ( & p [ 0 ] ) ;
if ( first_word ! = 0x4A414D01L )
return status ;
action_table = get_unaligned_be32 ( & p [ 4 ] ) ;
proc_table = get_unaligned_be32 ( & p [ 8 ] ) ;
str_table = get_unaligned_be32 ( & p [ 12 ] ) ;
note_strings = get_unaligned_be32 ( & p [ 16 ] ) ;
action_count = get_unaligned_be32 ( & p [ 48 ] ) ;
proc_count = get_unaligned_be32 ( & p [ 52 ] ) ;
if ( index > = action_count )
return status ;
act_name_id = get_unaligned_be32 ( & p [ action_table + ( 12 * index ) ] ) ;
act_desc_id = get_unaligned_be32 ( & p [ action_table + ( 12 * index ) + 4 ] ) ;
act_proc_id = get_unaligned_be32 ( & p [ action_table + ( 12 * index ) + 8 ] ) ;
* name = & p [ str_table + act_name_id ] ;
if ( act_desc_id < ( note_strings - str_table ) )
* description = & p [ str_table + act_desc_id ] ;
do {
act_proc_name = get_unaligned_be32 (
& p [ proc_table + ( 13 * act_proc_id ) ] ) ;
act_proc_attribute =
( p [ proc_table + ( 13 * act_proc_id ) + 8 ] & 0x03 ) ;
2011-08-13 11:34:09 +02:00
procptr =
2011-01-25 17:00:00 -03:00
kzalloc ( sizeof ( struct altera_procinfo ) ,
GFP_KERNEL ) ;
if ( procptr = = NULL )
status = - ENOMEM ;
else {
procptr - > name = & p [ str_table + act_proc_name ] ;
procptr - > attrs = act_proc_attribute ;
procptr - > next = NULL ;
/* add record to end of linked list */
if ( * proc_list = = NULL )
* proc_list = procptr ;
else {
tmpptr = * proc_list ;
while ( tmpptr - > next ! = NULL )
tmpptr = tmpptr - > next ;
tmpptr - > next = procptr ;
}
}
act_proc_id = get_unaligned_be32 (
& p [ proc_table + ( 13 * act_proc_id ) + 4 ] ) ;
} while ( ( act_proc_id ! = 0 ) & & ( act_proc_id < proc_count ) ) ;
return status ;
}
int altera_init ( struct altera_config * config , const struct firmware * fw )
{
struct altera_state * astate = NULL ;
struct altera_procinfo * proc_list = NULL ;
struct altera_procinfo * procptr = NULL ;
char * key = NULL ;
char * value = NULL ;
char * action_name = NULL ;
char * description = NULL ;
int exec_result = 0 ;
int exit_code = 0 ;
int format_version = 0 ;
int action_count = 0 ;
int procedure_count = 0 ;
int index = 0 ;
s32 offset = 0L ;
s32 error_address = 0L ;
2011-05-31 01:11:17 +02:00
int retval = 0 ;
2011-01-25 17:00:00 -03:00
2011-05-31 01:11:17 +02:00
key = kzalloc ( 33 , GFP_KERNEL ) ;
if ( ! key ) {
retval = - ENOMEM ;
goto out ;
}
value = kzalloc ( 257 , GFP_KERNEL ) ;
if ( ! value ) {
retval = - ENOMEM ;
goto free_key ;
}
2011-01-25 17:00:00 -03:00
astate = kzalloc ( sizeof ( struct altera_state ) , GFP_KERNEL ) ;
2011-05-31 01:11:17 +02:00
if ( ! astate ) {
retval = - ENOMEM ;
goto free_value ;
}
2011-01-25 17:00:00 -03:00
astate - > config = config ;
if ( ! astate - > config - > jtag_io ) {
2015-06-25 15:01:22 -07:00
dprintk ( " %s: using byteblaster! \n " , __func__ ) ;
2011-01-25 17:00:00 -03:00
astate - > config - > jtag_io = netup_jtag_io_lpt ;
}
altera_check_crc ( ( u8 * ) fw - > data , fw - > size ) ;
if ( debug ) {
altera_get_file_info ( ( u8 * ) fw - > data , fw - > size , & format_version ,
& action_count , & procedure_count ) ;
printk ( KERN_INFO " %s: File format is %s ByteCode format \n " ,
__func__ , ( format_version = = 2 ) ? " Jam STAPL " :
" pre-standardized Jam 1.1 " ) ;
while ( altera_get_note ( ( u8 * ) fw - > data , fw - > size ,
altera-stapl: altera_get_note: prevent write beyond end of 'key'
altera_get_note is called from altera_init, where key is kzalloc(33).
When the allocation functions are annotated to allow the compiler to see
the sizes of objects, and with FORTIFY_SOURCE, we see:
In file included from drivers/misc/altera-stapl/altera.c:14:0:
In function ‘strlcpy’,
inlined from ‘altera_init’ at drivers/misc/altera-stapl/altera.c:2189:5:
include/linux/string.h:378:4: error: call to ‘__write_overflow’ declared with attribute error: detected write beyond size of object passed as 1st parameter
__write_overflow();
^~~~~~~~~~~~~~~~~~
That refers to this code in altera_get_note:
if (key != NULL)
strlcpy(key, &p[note_strings +
get_unaligned_be32(
&p[note_table + (8 * i)])],
length);
The error triggers because the length of 'key' is 33, but the copy
uses length supplied as the 'length' parameter, which is always
256. Split the size parameter into key_len and val_len, and use the
appropriate length depending on what is being copied.
Detected by compiler error, only compile-tested.
Cc: "Igor M. Liplianin" <liplianin@netup.ru>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Link: https://lore.kernel.org/r/20200120074344.504-2-dja@axtens.net
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/202002251042.D898E67AC@keescook
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-02-25 10:44:27 -08:00
& offset , key , value , 32 , 256 ) = = 0 )
2011-01-25 17:00:00 -03:00
printk ( KERN_INFO " %s: NOTE \" %s \" = \" %s \" \n " ,
__func__ , key , value ) ;
}
if ( debug & & ( format_version = = 2 ) & & ( action_count > 0 ) ) {
printk ( KERN_INFO " %s: Actions available: \n " , __func__ ) ;
for ( index = 0 ; index < action_count ; + + index ) {
altera_get_act_info ( ( u8 * ) fw - > data , fw - > size ,
index , & action_name ,
& description ,
& proc_list ) ;
if ( description = = NULL )
printk ( KERN_INFO " %s: %s \n " ,
__func__ ,
action_name ) ;
else
printk ( KERN_INFO " %s: %s \" %s \" \n " ,
__func__ ,
action_name ,
description ) ;
procptr = proc_list ;
while ( procptr ! = NULL ) {
if ( procptr - > attrs ! = 0 )
printk ( KERN_INFO " %s: %s (%s) \n " ,
__func__ ,
procptr - > name ,
( procptr - > attrs = = 1 ) ?
" optional " : " recommended " ) ;
proc_list = procptr - > next ;
kfree ( procptr ) ;
procptr = proc_list ;
}
}
printk ( KERN_INFO " \n " ) ;
}
exec_result = altera_execute ( astate , ( u8 * ) fw - > data , fw - > size ,
& error_address , & exit_code , & format_version ) ;
if ( exit_code )
exec_result = - EREMOTEIO ;
if ( ( format_version = = 2 ) & & ( exec_result = = - EINVAL ) ) {
if ( astate - > config - > action = = NULL )
printk ( KERN_ERR " %s: error: no action specified for "
" Jam STAPL file. \n program terminated. \n " ,
__func__ ) ;
else
printk ( KERN_ERR " %s: error: action \" %s \" "
" is not supported "
" for this Jam STAPL file. \n "
" Program terminated. \n " , __func__ ,
astate - > config - > action ) ;
} else if ( exec_result )
printk ( KERN_ERR " %s: error %d \n " , __func__ , exec_result ) ;
kfree ( astate ) ;
2011-05-31 01:11:17 +02:00
free_value :
kfree ( value ) ;
free_key :
kfree ( key ) ;
out :
return retval ;
2011-01-25 17:00:00 -03:00
}
EXPORT_SYMBOL ( altera_init ) ;