mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 18:14:07 +08:00
media: lirc: validate scancode for transmit
Ensure we reject an attempt to transmit invalid scancodes. Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
a60d64b15c
commit
49a4b36ada
@ -126,6 +126,16 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
|
||||
if (scan.flags || scan.keycode || scan.timestamp)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The scancode field in lirc_scancode is 64-bit simply
|
||||
* to future-proof it, since there are IR protocols encode
|
||||
* use more than 32 bits. For now only 32-bit protocols
|
||||
* are supported.
|
||||
*/
|
||||
if (scan.scancode > U32_MAX ||
|
||||
!rc_validate_scancode(scan.rc_proto, scan.scancode))
|
||||
return -EINVAL;
|
||||
|
||||
raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
|
||||
if (!raw)
|
||||
return -ENOMEM;
|
||||
|
@ -150,6 +150,7 @@ static inline bool is_timing_event(struct ir_raw_event ev)
|
||||
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
|
||||
|
||||
/* functions for IR encoders */
|
||||
bool rc_validate_scancode(enum rc_proto proto, u32 scancode);
|
||||
|
||||
static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
|
||||
unsigned int pulse,
|
||||
|
@ -775,6 +775,37 @@ void rc_keydown_notimeout(struct rc_dev *dev, enum rc_proto protocol,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
|
||||
|
||||
/**
|
||||
* rc_validate_scancode() - checks that a scancode is valid for a protocol
|
||||
* @proto: protocol
|
||||
* @scancode: scancode
|
||||
*/
|
||||
bool rc_validate_scancode(enum rc_proto proto, u32 scancode)
|
||||
{
|
||||
switch (proto) {
|
||||
case RC_PROTO_NECX:
|
||||
if ((((scancode >> 16) ^ ~(scancode >> 8)) & 0xff) == 0)
|
||||
return false;
|
||||
break;
|
||||
case RC_PROTO_NEC32:
|
||||
if ((((scancode >> 24) ^ ~(scancode >> 16)) & 0xff) == 0)
|
||||
return false;
|
||||
break;
|
||||
case RC_PROTO_RC6_MCE:
|
||||
if ((scancode & 0xffff0000) != 0x800f0000)
|
||||
return false;
|
||||
break;
|
||||
case RC_PROTO_RC6_6A_32:
|
||||
if ((scancode & 0xffff0000) == 0x800f0000)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* rc_validate_filter() - checks that the scancode and mask are valid and
|
||||
* provides sensible defaults
|
||||
@ -794,26 +825,8 @@ static int rc_validate_filter(struct rc_dev *dev,
|
||||
|
||||
mask = protocols[protocol].scancode_bits;
|
||||
|
||||
switch (protocol) {
|
||||
case RC_PROTO_NECX:
|
||||
if ((((s >> 16) ^ ~(s >> 8)) & 0xff) == 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RC_PROTO_NEC32:
|
||||
if ((((s >> 24) ^ ~(s >> 16)) & 0xff) == 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RC_PROTO_RC6_MCE:
|
||||
if ((s & 0xffff0000) != 0x800f0000)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RC_PROTO_RC6_6A_32:
|
||||
if ((s & 0xffff0000) == 0x800f0000)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!rc_validate_scancode(protocol, s))
|
||||
return -EINVAL;
|
||||
|
||||
filter->data &= mask;
|
||||
filter->mask &= mask;
|
||||
|
Loading…
Reference in New Issue
Block a user