18
18
#define LOG_TAG " IOMX"
19
19
#include < utils/Log.h>
20
20
21
+ #include < sys/mman.h>
22
+
21
23
#include < binder/IMemory.h>
22
24
#include < binder/Parcel.h>
23
25
#include < media/IOMX.h>
@@ -598,38 +600,70 @@ status_t BnOMX::onTransact(
598
600
599
601
size_t size = data.readInt32 ();
600
602
601
- status_t err = NO_MEMORY;
602
- void *params = calloc (size, 1 );
603
- if (params) {
604
- err = data.read (params, size);
605
- if (err != OK) {
606
- android_errorWriteLog (0x534e4554 , " 26914474" );
603
+ status_t err = NOT_ENOUGH_DATA;
604
+ void *params = NULL ;
605
+ size_t pageSize = 0 ;
606
+ size_t allocSize = 0 ;
607
+ if (code != SET_INTERNAL_OPTION && size < 8 ) {
608
+ // we expect the structure to contain at least the size and
609
+ // version, 8 bytes total
610
+ ALOGE (" b/27207275 (%zu)" , size);
611
+ android_errorWriteLog (0x534e4554 , " 27207275" );
612
+ } else {
613
+ err = NO_MEMORY;
614
+ pageSize = (size_t ) sysconf (_SC_PAGE_SIZE);
615
+ if (size > SIZE_MAX - (pageSize * 2 )) {
616
+ ALOGE (" requested param size too big" );
607
617
} else {
608
- switch (code) {
609
- case GET_PARAMETER:
610
- err = getParameter (node, index, params, size);
611
- break ;
612
- case SET_PARAMETER:
613
- err = setParameter (node, index, params, size);
614
- break ;
615
- case GET_CONFIG:
616
- err = getConfig (node, index, params, size);
617
- break ;
618
- case SET_CONFIG:
619
- err = setConfig (node, index, params, size);
620
- break ;
621
- case SET_INTERNAL_OPTION:
622
- {
623
- InternalOptionType type =
624
- (InternalOptionType)data.readInt32 ();
625
-
626
- err = setInternalOption (node, index, type, params, size);
627
- break ;
618
+ allocSize = (size + pageSize * 2 ) & ~(pageSize - 1 );
619
+ params = mmap (NULL , allocSize, PROT_READ | PROT_WRITE,
620
+ MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */ , 0 /* offset */ );
621
+ }
622
+ if (params != MAP_FAILED) {
623
+ err = data.read (params, size);
624
+ if (err != OK) {
625
+ android_errorWriteLog (0x534e4554 , " 26914474" );
626
+ } else {
627
+ err = NOT_ENOUGH_DATA;
628
+ OMX_U32 declaredSize = *(OMX_U32*)params;
629
+ if (code != SET_INTERNAL_OPTION && declaredSize > size) {
630
+ // the buffer says it's bigger than it actually is
631
+ ALOGE (" b/27207275 (%u/%zu)" , declaredSize, size);
632
+ android_errorWriteLog (0x534e4554 , " 27207275" );
633
+ } else {
634
+ // mark the last page as inaccessible, to avoid exploitation
635
+ // of codecs that access past the end of the allocation because
636
+ // they didn't check the size
637
+ mprotect ((char *)params + allocSize - pageSize, pageSize, PROT_NONE);
638
+ switch (code) {
639
+ case GET_PARAMETER:
640
+ err = getParameter (node, index, params, size);
641
+ break ;
642
+ case SET_PARAMETER:
643
+ err = setParameter (node, index, params, size);
644
+ break ;
645
+ case GET_CONFIG:
646
+ err = getConfig (node, index, params, size);
647
+ break ;
648
+ case SET_CONFIG:
649
+ err = setConfig (node, index, params, size);
650
+ break ;
651
+ case SET_INTERNAL_OPTION:
652
+ {
653
+ InternalOptionType type =
654
+ (InternalOptionType)data.readInt32 ();
655
+
656
+ err = setInternalOption (node, index, type, params, size);
657
+ break ;
658
+ }
659
+
660
+ default :
661
+ TRESPASS ();
662
+ }
628
663
}
629
-
630
- default :
631
- TRESPASS ();
632
664
}
665
+ } else {
666
+ ALOGE (" couldn't map: %s" , strerror (errno));
633
667
}
634
668
}
635
669
@@ -639,7 +673,9 @@ status_t BnOMX::onTransact(
639
673
reply->write (params, size);
640
674
}
641
675
642
- free (params);
676
+ if (params) {
677
+ munmap (params, allocSize);
678
+ }
643
679
params = NULL ;
644
680
645
681
return NO_ERROR;
0 commit comments