Add a way to disable less well tested operations (#2636)
* quick proposal warn on startup if untrusted operations might run use vips_block_untrusted_set() to block untrusted operations, set an env var or make a file to stop the warning * mark fits, nifti and svg as untrusted * remove the annoying "untrusted" warning message better to warn on the download page leave vips_block_untrusted_set() since it's obviously useful * separate UNTRUSTED and BLOCKED * typos * add VIPS_BLOCK_UNTRUSTED env var * move BLOCK_UNTRUSTED after plugin load obviously, ooops * add a test, disable *magick although *magick is fuzzed, it's probably safer to disable it in untrusted environments * mark some more operations as untrusted
This commit is contained in:
parent
6eae6fcf4b
commit
eba9ec0dd7
@ -7,6 +7,7 @@
|
||||
- add spngsave
|
||||
- jpeg2000 load left-justifies bitdepth
|
||||
- add "password" option to pdfload
|
||||
- add vips_operation_block_set(), vips_operation_block_untrusted_set()
|
||||
- improve the pixel rng
|
||||
- new meson build system [tintou]
|
||||
- improve introspection annotations [tintou]
|
||||
|
@ -109,6 +109,7 @@ vips_foreign_load_analyze_class_init( VipsForeignLoadAnalyzeClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -118,6 +119,11 @@ vips_foreign_load_analyze_class_init( VipsForeignLoadAnalyzeClass *class )
|
||||
object_class->nickname = "analyzeload";
|
||||
object_class->description = _( "load an Analyze6 image" );
|
||||
|
||||
/* This is fuzzed, but you're unlikely to want to use it on
|
||||
* untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips_foreign_analyze_suffs;
|
||||
|
||||
/* is_a() is not that quick ... lower the priority.
|
||||
|
@ -470,6 +470,7 @@ vips_foreign_load_csv_class_init( VipsForeignLoadCsvClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_csv_dispose;
|
||||
@ -480,6 +481,11 @@ vips_foreign_load_csv_class_init( VipsForeignLoadCsvClass *class )
|
||||
object_class->description = _( "load csv" );
|
||||
object_class->build = vips_foreign_load_csv_build;
|
||||
|
||||
/* This is fuzzed, but you're unlikely to want to use it on
|
||||
* untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
load_class->get_flags = vips_foreign_load_csv_get_flags;
|
||||
load_class->header = vips_foreign_load_csv_header;
|
||||
load_class->load = vips_foreign_load_csv_load;
|
||||
|
@ -173,6 +173,7 @@ vips_foreign_load_fits_class_init( VipsForeignLoadFitsClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -184,6 +185,11 @@ vips_foreign_load_fits_class_init( VipsForeignLoadFitsClass *class )
|
||||
object_class->description = _( "FITS loader base class" );
|
||||
object_class->build = vips_foreign_load_fits_build;
|
||||
|
||||
/* cfitsio has not been fuzzed, so should not be used with
|
||||
* untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* is_a() is not that quick ... lower the priority.
|
||||
*/
|
||||
foreign_class->priority = -50;
|
||||
|
@ -119,6 +119,7 @@ vips_foreign_save_fits_class_init( VipsForeignSaveFitsClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
@ -129,6 +130,11 @@ vips_foreign_save_fits_class_init( VipsForeignSaveFitsClass *class )
|
||||
object_class->description = _( "save image to fits file" );
|
||||
object_class->build = vips_foreign_save_fits_build;
|
||||
|
||||
/* cfitsio has not been fuzzed, so should not be used with
|
||||
* untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips__fits_suffs;
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||
|
@ -1165,8 +1165,8 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class )
|
||||
object_class->build = vips_foreign_load_build;
|
||||
object_class->summary_class = vips_foreign_load_summary_class;
|
||||
object_class->new_from_string = vips_foreign_load_new_from_string;
|
||||
object_class->nickname = "fileload";
|
||||
object_class->description = _( "file loaders" );
|
||||
object_class->nickname = "load";
|
||||
object_class->description = _( "loaders" );
|
||||
|
||||
operation_class->get_flags = vips_foreign_load_operation_get_flags;
|
||||
|
||||
@ -1767,8 +1767,8 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class )
|
||||
object_class->build = vips_foreign_save_build;
|
||||
object_class->summary_class = vips_foreign_save_summary_class;
|
||||
object_class->new_from_string = vips_foreign_save_new_from_string;
|
||||
object_class->nickname = "filesave";
|
||||
object_class->description = _( "file savers" );
|
||||
object_class->nickname = "save";
|
||||
object_class->description = _( "savers" );
|
||||
|
||||
/* All savers are sequential by definition. Things like tiled tiff
|
||||
* write and interlaced png write, which are not, add extra caches
|
||||
|
@ -1038,6 +1038,7 @@ vips_foreign_load_jp2k_class_init( VipsForeignLoadJp2kClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_jp2k_dispose;
|
||||
@ -1048,6 +1049,10 @@ vips_foreign_load_jp2k_class_init( VipsForeignLoadJp2kClass *class )
|
||||
object_class->description = _( "load JPEG2000 image" );
|
||||
object_class->build = vips_foreign_load_jp2k_build;
|
||||
|
||||
/* OpenJPEG is fuzzed, but not by us.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
load_class->get_flags = vips_foreign_load_jp2k_get_flags;
|
||||
load_class->header = vips_foreign_load_jp2k_header;
|
||||
load_class->load = vips_foreign_load_jp2k_load;
|
||||
|
@ -697,6 +697,7 @@ vips_foreign_load_jxl_class_init( VipsForeignLoadJxlClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_jxl_dispose;
|
||||
@ -707,6 +708,11 @@ vips_foreign_load_jxl_class_init( VipsForeignLoadJxlClass *class )
|
||||
object_class->description = _( "load JPEG-XL image" );
|
||||
object_class->build = vips_foreign_load_jxl_build;
|
||||
|
||||
/* libjxl is fuzzed, but it's relatively young and bugs are
|
||||
* still being found in jan 2022. Revise this status soon.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
load_class->get_flags = vips_foreign_load_jxl_get_flags;
|
||||
load_class->header = vips_foreign_load_jxl_header;
|
||||
load_class->load = vips_foreign_load_jxl_load;
|
||||
|
@ -451,6 +451,7 @@ vips_foreign_save_jxl_class_init( VipsForeignSaveJxlClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
@ -462,6 +463,11 @@ vips_foreign_save_jxl_class_init( VipsForeignSaveJxlClass *class )
|
||||
object_class->description = _( "save image in JPEG-XL format" );
|
||||
object_class->build = vips_foreign_save_jxl_build;
|
||||
|
||||
/* libjxl is fuzzed, but it's still relatively young and bugs are
|
||||
* still being found in jan 2022. Revise this status soon.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips__jxl_suffs;
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||
|
@ -116,6 +116,11 @@ vips_foreign_load_magick_class_init( VipsForeignLoadMagickClass *class )
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_NOCACHE;
|
||||
|
||||
/* *magick is fuzzed, but it's such a huge thing it's safer to
|
||||
* disable it.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* We need to be well to the back of the queue since vips's
|
||||
* dedicated loaders are usually preferable.
|
||||
*/
|
||||
|
@ -341,6 +341,7 @@ vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -352,6 +353,15 @@ vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
||||
object_class->description = _( "load with ImageMagick7" );
|
||||
object_class->build = vips_foreign_load_magick7_build;
|
||||
|
||||
/* Don't cache magickload: it can gobble up memory and disc.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_NOCACHE;
|
||||
|
||||
/* *magick is fuzzed, but it's such a huge thing it's safer to
|
||||
* disable it.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* We need to be well to the back of the queue since vips's
|
||||
* dedicated loaders are usually preferable.
|
||||
*/
|
||||
|
@ -111,6 +111,7 @@ vips_foreign_load_mat_class_init( VipsForeignLoadMatClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -120,6 +121,10 @@ vips_foreign_load_mat_class_init( VipsForeignLoadMatClass *class )
|
||||
object_class->nickname = "matload";
|
||||
object_class->description = _( "load mat from file" );
|
||||
|
||||
/* libmatio is fuzzed, but not by us.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips__mat_suffs;
|
||||
|
||||
load_class->is_a = vips__mat_ismat;
|
||||
|
@ -580,6 +580,7 @@ vips_foreign_load_nifti_class_init( VipsForeignLoadNiftiClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -591,6 +592,11 @@ vips_foreign_load_nifti_class_init( VipsForeignLoadNiftiClass *class )
|
||||
object_class->description = _( "load a NIFTI image" );
|
||||
object_class->build = vips_foreign_load_nifti_build;
|
||||
|
||||
/* nificlib has not been fuzzed, so should not be used with
|
||||
* untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* is_a() is not that quick ... lower the priority.
|
||||
*/
|
||||
foreign_class->priority = -50;
|
||||
|
@ -417,6 +417,7 @@ vips_foreign_save_nifti_class_init( VipsForeignSaveNiftiClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
@ -428,6 +429,11 @@ vips_foreign_save_nifti_class_init( VipsForeignSaveNiftiClass *class )
|
||||
object_class->description = _( "save image to nifti file" );
|
||||
object_class->build = vips_foreign_save_nifti_build;
|
||||
|
||||
/* nificlib has not been fuzzed, so should not be used with
|
||||
* untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips_foreign_nifti_suffs;
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||
|
@ -118,6 +118,7 @@ vips_foreign_load_openexr_class_init( VipsForeignLoadOpenexrClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -127,6 +128,10 @@ vips_foreign_load_openexr_class_init( VipsForeignLoadOpenexrClass *class )
|
||||
object_class->nickname = "openexrload";
|
||||
object_class->description = _( "load an OpenEXR image" );
|
||||
|
||||
/* OpenEXR is fuzzed, but not by us.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips_foreign_openexr_suffs;
|
||||
|
||||
/* We are fast at is_a(), so high priority.
|
||||
|
@ -1063,8 +1063,16 @@ vips_foreign_load_openslide_source_class_init(
|
||||
object_class->description = _( "load source with OpenSlide" );
|
||||
object_class->build = vips_foreign_load_openslide_source_build;
|
||||
|
||||
/* libopenslide does not try to recover from errors, so it's not safe
|
||||
* to cache.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_NOCACHE;
|
||||
|
||||
/* openslide has not been fuzzed and is largly unmaintained, so should
|
||||
* not be used with untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
load_class->is_a_source =
|
||||
vips_foreign_load_openslide_source_is_a_source;
|
||||
|
||||
|
@ -188,7 +188,8 @@ vips_foreign_load_pdf_build( VipsObject *object )
|
||||
|
||||
pdf->stream = vips_g_input_stream_new_from_source( pdf->source );
|
||||
if( !(pdf->doc = poppler_document_new_from_stream( pdf->stream,
|
||||
vips_source_length( pdf->source ), pdf->password, NULL, &error )) ) {
|
||||
vips_source_length( pdf->source ), pdf->password,
|
||||
NULL, &error )) ) {
|
||||
vips_g_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
@ -228,7 +229,8 @@ vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no )
|
||||
printf( "vips_foreign_load_pdf_get_page: %d\n", page_no );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(pdf->page = poppler_document_get_page( pdf->doc, page_no )) ) {
|
||||
if( !(pdf->page =
|
||||
poppler_document_get_page( pdf->doc, page_no )) ) {
|
||||
vips_error( class->nickname,
|
||||
_( "unable to load page %d" ), page_no );
|
||||
return( -1 );
|
||||
|
@ -736,6 +736,7 @@ vips_foreign_load_ppm_class_init( VipsForeignLoadPpmClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -747,6 +748,10 @@ vips_foreign_load_ppm_class_init( VipsForeignLoadPpmClass *class )
|
||||
object_class->description = _( "load ppm base class" );
|
||||
object_class->build = vips_foreign_load_ppm_build;
|
||||
|
||||
/* You're unlikely to want to use this on untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
foreign_class->suffs = vips__ppm_suffs;
|
||||
|
||||
/* We are fast at is_a(), so high priority.
|
||||
|
@ -116,6 +116,7 @@ vips_foreign_load_rad_class_init( VipsForeignLoadRadClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -124,6 +125,10 @@ vips_foreign_load_rad_class_init( VipsForeignLoadRadClass *class )
|
||||
object_class->nickname = "radload_base";
|
||||
object_class->description = _( "load rad base class" );
|
||||
|
||||
/* You're unlikely to want to use this on untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* is_a() is not that quick ... lower the priority.
|
||||
*/
|
||||
foreign_class->priority = -50;
|
||||
|
@ -117,11 +117,16 @@ vips_foreign_load_raw_class_init( VipsForeignLoadRawClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
/* You're unlikely to want to use this on untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
object_class->nickname = "rawload";
|
||||
object_class->description = _( "load raw data from a file" );
|
||||
|
||||
|
@ -504,6 +504,7 @@ vips_foreign_load_svg_class_init( VipsForeignLoadSvgClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -514,6 +515,11 @@ vips_foreign_load_svg_class_init( VipsForeignLoadSvgClass *class )
|
||||
object_class->nickname = "svgload_base";
|
||||
object_class->description = _( "load SVG with rsvg" );
|
||||
|
||||
/* librsvg has not been fuzzed, so should not be used with
|
||||
* untrusted input unless you are very careful.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* is_a() is not that quick ... lower the priority.
|
||||
*/
|
||||
foreign_class->priority = -5;
|
||||
|
@ -439,6 +439,7 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = (VipsOperationClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
@ -450,6 +451,11 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class )
|
||||
object_class->description = _( "save with ImageMagick" );
|
||||
object_class->build = vips_foreign_save_magick_build;
|
||||
|
||||
/* *magick is fuzzed, but it's such a huge thing it's safer to
|
||||
* disable it.
|
||||
*/
|
||||
operation_class->flags = VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* We need to be well to the back of the queue since vips's
|
||||
* dedicated savers are usually preferable.
|
||||
*/
|
||||
|
@ -145,6 +145,7 @@ vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
@ -153,6 +154,10 @@ vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class )
|
||||
object_class->nickname = "vipsload_base";
|
||||
object_class->description = _( "load vips base class" );
|
||||
|
||||
/* You're unlikely to want to use this on untrusted files.
|
||||
*/
|
||||
operation_class->flags |= VIPS_OPERATION_UNTRUSTED;
|
||||
|
||||
/* We are fast at is_a(), so high priority.
|
||||
*/
|
||||
foreign_class->priority = 200;
|
||||
|
@ -125,10 +125,6 @@ extern int vips__leak;
|
||||
*/
|
||||
extern int vips__progress;
|
||||
|
||||
/* Leak check on exit.
|
||||
*/
|
||||
extern int vips__leak;
|
||||
|
||||
/* Show info messages. Handy for debugging.
|
||||
*/
|
||||
extern int vips__info;
|
||||
|
@ -46,7 +46,9 @@ typedef enum /*< flags >*/ {
|
||||
VIPS_OPERATION_SEQUENTIAL = 1,
|
||||
VIPS_OPERATION_SEQUENTIAL_UNBUFFERED = 2,
|
||||
VIPS_OPERATION_NOCACHE = 4,
|
||||
VIPS_OPERATION_DEPRECATED = 8
|
||||
VIPS_OPERATION_DEPRECATED = 8,
|
||||
VIPS_OPERATION_UNTRUSTED = 16,
|
||||
VIPS_OPERATION_BLOCKED = 32
|
||||
} VipsOperationFlags;
|
||||
|
||||
#define VIPS_TYPE_OPERATION (vips_operation_get_type())
|
||||
@ -141,6 +143,8 @@ void vips_cache_set_trace( gboolean trace );
|
||||
void vips_concurrency_set( int concurrency );
|
||||
int vips_concurrency_get( void );
|
||||
|
||||
void vips_operation_block_set( const char *name, gboolean state );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -181,7 +181,9 @@ void vips_thread_shutdown( void );
|
||||
|
||||
void vips_add_option_entries( GOptionGroup *option_group );
|
||||
|
||||
extern void vips_leak_set( gboolean leak );
|
||||
void vips_leak_set( gboolean leak );
|
||||
|
||||
void vips_block_untrusted_set( gboolean state );
|
||||
|
||||
const char *vips_version_string( void );
|
||||
int vips_version( int flag );
|
||||
|
@ -972,6 +972,8 @@ vips_operation_flags_get_type( void )
|
||||
{VIPS_OPERATION_SEQUENTIAL_UNBUFFERED, "VIPS_OPERATION_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"},
|
||||
{VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"},
|
||||
{VIPS_OPERATION_DEPRECATED, "VIPS_OPERATION_DEPRECATED", "deprecated"},
|
||||
{VIPS_OPERATION_UNTRUSTED, "VIPS_OPERATION_UNTRUSTED", "untrusted"},
|
||||
{VIPS_OPERATION_BLOCKED, "VIPS_OPERATION_BLOCKED", "blocked"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -186,9 +186,6 @@ vips_get_prgname( void )
|
||||
* VIPS_INIT:
|
||||
* @ARGV0: name of application
|
||||
*
|
||||
* gtk-doc mistakenly tags this macro as deprecated for unknown reasons. It is
|
||||
* *NOT* deprecated, please ignore the warning above.
|
||||
*
|
||||
* VIPS_INIT() starts up the world of VIPS. You should call this on
|
||||
* program startup before using any other VIPS operations. If you do not call
|
||||
* VIPS_INIT(), VIPS will call it for you when you use your first VIPS
|
||||
@ -647,8 +644,6 @@ vips_init( const char *argv0 )
|
||||
g_quark_from_static_string( "vips-image-pixels" );
|
||||
#endif /*DEBUG_LEAK*/
|
||||
|
||||
done = TRUE;
|
||||
|
||||
/* If VIPS_WARNING is defined, suppress all warning messages from vips.
|
||||
*
|
||||
* Libraries should not call g_log_set_handler(), it is
|
||||
@ -664,11 +659,18 @@ vips_init( const char *argv0 )
|
||||
g_log_set_handler( G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
empty_log_handler, NULL );
|
||||
|
||||
/* Block any untrusted operations. This must come after plugin load.
|
||||
*/
|
||||
if( g_getenv( "VIPS_BLOCK_UNTRUSTED" ) )
|
||||
vips_block_untrusted_set( TRUE );
|
||||
|
||||
/* Set a minimum stacksize, if we can.
|
||||
*/
|
||||
if( (vips_min_stack_size = g_getenv( "VIPS_MIN_STACK_SIZE" )) )
|
||||
(void) set_stacksize( vips__parse_size( vips_min_stack_size ) );
|
||||
|
||||
done = TRUE;
|
||||
|
||||
vips__thread_gate_stop( "init: startup" );
|
||||
|
||||
return( 0 );
|
||||
@ -1309,3 +1311,39 @@ vips__get_sizeof_vipsobject( void )
|
||||
return( sizeof( VipsObject ) );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_block_untrusted_set_operation( VipsOperationClass *class, gboolean *state )
|
||||
{
|
||||
g_assert( VIPS_IS_OPERATION_CLASS( class ) );
|
||||
|
||||
if( class->flags & VIPS_OPERATION_UNTRUSTED )
|
||||
vips_operation_block_set( VIPS_OBJECT_CLASS( class )->nickname,
|
||||
*state );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_block_untrusted_set:
|
||||
* @state: the block state to set
|
||||
*
|
||||
* Set the block state on all untrusted operations.
|
||||
*
|
||||
* |[
|
||||
* vips_block_untrusted_set( TRUE );
|
||||
* ]|
|
||||
*
|
||||
* Will block all untrusted operations from running.
|
||||
*
|
||||
* Use `vips -l` at the command-line to see the class hierarchy and which
|
||||
* operations are marked as untrusted.
|
||||
*
|
||||
* Set the environment variable `VIPS_BLOCK_UNTRUSTED` to block all untrusted
|
||||
* operations on vips_init().
|
||||
*/
|
||||
void
|
||||
vips_block_untrusted_set( gboolean state )
|
||||
{
|
||||
vips_class_map_all( g_type_from_name( "VipsOperation" ),
|
||||
(VipsClassMapFn) vips_block_untrusted_set_operation, &state );
|
||||
}
|
||||
|
@ -171,6 +171,8 @@
|
||||
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially with a small buffer
|
||||
* @VIPS_OPERATION_NOCACHE: must not be cached
|
||||
* @VIPS_OPERATION_DEPRECATED: a compatibility thing
|
||||
* @VIPS_OPERATION_UNTRUSTED: not hardened for untrusted input
|
||||
* @VIPS_OPERATION_BLOCKED: prevent this operation from running
|
||||
*
|
||||
* Flags we associate with an operation.
|
||||
*
|
||||
@ -193,6 +195,13 @@
|
||||
*
|
||||
* @VIPS_OPERATION_DEPRECATED means this is an old operation kept in vips for
|
||||
* compatibility only and should be hidden from users.
|
||||
*
|
||||
* @VIPS_OPERATION_UNTRUSTED means the operation depends on external libraries which have
|
||||
* not been hardened against attack. It should probably not be used on untrusted input.
|
||||
* Use vips_operation_block_untrusted() to block all untrusted operations.
|
||||
*
|
||||
* @VIPS_OPERATION_BLOCKED means the operation is prevented from executing. Use
|
||||
* vips_operation_block_set() to enable and disable groups of operations.
|
||||
*/
|
||||
|
||||
/* Abstract base class for operations.
|
||||
@ -531,6 +540,30 @@ vips_operation_vips_operation_print_summary_arg( VipsObject *object,
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_operation_build( VipsObject *object )
|
||||
{
|
||||
VipsOperationClass *class = VIPS_OPERATION_GET_CLASS( object );
|
||||
|
||||
#ifdef VIPS_DEBUG
|
||||
printf( "vips_operation_build: " );
|
||||
vips_object_print_name( object );
|
||||
printf( "\n" );
|
||||
#endif /*VIPS_DEBUG*/
|
||||
|
||||
if( class->flags & VIPS_OPERATION_BLOCKED ) {
|
||||
vips_error( VIPS_OBJECT_CLASS( class )->nickname,
|
||||
"%s", _( "operation is blocked" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_operation_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_operation_summary( VipsObject *object, VipsBuf *buf )
|
||||
{
|
||||
@ -564,10 +597,11 @@ vips_operation_class_init( VipsOperationClass *class )
|
||||
gobject_class->finalize = vips_operation_finalize;
|
||||
gobject_class->dispose = vips_operation_dispose;
|
||||
|
||||
vobject_class->nickname = "operation";
|
||||
vobject_class->description = _( "operations" );
|
||||
vobject_class->build = vips_operation_build;
|
||||
vobject_class->summary = vips_operation_summary;
|
||||
vobject_class->dump = vips_operation_dump;
|
||||
vobject_class->nickname = "operation";
|
||||
vobject_class->description = _( "operations" );
|
||||
|
||||
class->usage = vips_operation_usage;
|
||||
class->get_flags = vips_operation_real_get_flags;
|
||||
@ -636,9 +670,8 @@ vips_operation_invalidate( VipsOperation *operation )
|
||||
* Return a new #VipsOperation with the specified nickname. Useful for
|
||||
* language bindings.
|
||||
*
|
||||
* You'll need to set
|
||||
* any arguments and build the operation before you can use it. See
|
||||
* vips_call() for a higher-level way to make new operations.
|
||||
* You'll need to set any arguments and build the operation before you can use
|
||||
* it. See vips_call() for a higher-level way to make new operations.
|
||||
*
|
||||
* Returns: (transfer full): the new operation.
|
||||
*/
|
||||
@ -1393,3 +1426,57 @@ vips_call_argv( VipsOperation *operation, int argc, char **argv )
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_operation_block_set_operation( VipsOperationClass *class, gboolean *state )
|
||||
{
|
||||
g_assert( VIPS_IS_OPERATION_CLASS( class ) );
|
||||
|
||||
#ifdef VIPS_DEBUG
|
||||
if( ((class->flags & VIPS_OPERATION_BLOCKED) != 0) != *state )
|
||||
VIPS_DEBUG_MSG( "vips_operation_block_set_operation: "
|
||||
"setting block state on %s = %d\n",
|
||||
VIPS_OBJECT_CLASS( class )->nickname, *state );
|
||||
#endif
|
||||
|
||||
if( state )
|
||||
class->flags |= VIPS_OPERATION_BLOCKED;
|
||||
else
|
||||
class->flags &= ~VIPS_OPERATION_BLOCKED;
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_operation_block_set:
|
||||
* @name: set block state at this point and below
|
||||
* @state: the block state to set
|
||||
*
|
||||
* Set the block state on all operations in the libvips class hierarchy at
|
||||
* @name and below.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* |[
|
||||
* vips_operation_block_set( "load", TRUE );
|
||||
* vips_operation_block_set( "jpegload_base", FALSE );
|
||||
* ]|
|
||||
*
|
||||
* Will block all load operations, except JPEG.
|
||||
*
|
||||
* Use `vips -l` at the command-line to see the class hierarchy.
|
||||
*
|
||||
* This call does nothing if the named operation is not found.
|
||||
*
|
||||
* See also: vips_block_untrusted_set().
|
||||
*/
|
||||
void
|
||||
vips_operation_block_set( const char *name, gboolean state )
|
||||
{
|
||||
GType base;
|
||||
|
||||
if( (base = vips_type_find( "VipsOperation", name )) )
|
||||
vips_class_map_all( base,
|
||||
(VipsClassMapFn) vips_operation_block_set_operation,
|
||||
&state );
|
||||
}
|
||||
|
@ -207,3 +207,16 @@ if test_supported dzsave; then
|
||||
test_saver copy $image .dz
|
||||
test_saver copy $image .dz[container=zip]
|
||||
fi
|
||||
|
||||
# test blocked and untrusted
|
||||
if test_supported magicksave; then
|
||||
printf "testing VIPS_BLOCK_UNTRUSTED with imagemagick ... "
|
||||
export VIPS_BLOCK_UNTRUSTED=1
|
||||
if vips magicksave $matlab $tmp/block.png; then
|
||||
echo "failed to block imagemagick"
|
||||
exit 1
|
||||
fi
|
||||
echo "ok"
|
||||
unset VIPS_BLOCK_UNTRUSTED
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user