@ -299,30 +299,31 @@ proxy_context_submit_cmd(struct virgl_context *base, const void *buffer, size_t
return reply . ok ? 0 : - 1 ;
return reply . ok ? 0 : - 1 ;
}
}
static int
static bool
alloc_memfd ( const char * name , size_t size , void * * out_ptr )
validate_resource_fd_shm ( int fd , uint64_t expected_size )
{
{
int fd = os_create_anonymous_file ( size , name ) ;
static const int required_seals = F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW ;
if ( fd < 0 )
static const int blocked_seals = F_SEAL_WRITE ;
return - 1 ;
int ret = fcntl ( fd , F_ADD_SEALS , F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW ) ;
const int seals = fcntl ( fd , F_GET_SEALS ) ;
if ( ret )
if ( ( seals & required_seals ) ! = required_seals ) {
goto fail ;
proxy_log ( " failed to validate shm seals(%d): required(%d) " , seals , required_seals ) ;
return false ;
if ( ! out_ptr )
}
return fd ;
void * ptr = mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 ) ;
if ( seals & blocked_seals ) {
if ( ptr = = MAP_FAILED )
proxy_log ( " failed to validate shm seals(%d): blocked(%d) " , seals , blocked_seals ) ;
goto fail ;
return false ;
}
* out_ptr = ptr ;
const uint64_t size = lseek64 ( fd , 0 , SEEK_END ) ;
return fd ;
if ( size ! = expected_size ) {
proxy_log ( " failed to validate shm size(% " PRIu64 " ) expected(% " PRIu64 " ) " , size ,
expected_size ) ;
return false ;
}
fail :
return true ;
close ( fd ) ;
return - 1 ;
}
}
static int
static int
@ -335,18 +336,6 @@ proxy_context_get_blob(struct virgl_context *base,
{
{
struct proxy_context * ctx = ( struct proxy_context * ) base ;
struct proxy_context * ctx = ( struct proxy_context * ) base ;
/* hijack blob_id == 0 && blob_flags == MMAPABLE to save roundtrips */
if ( ! blob_id & & blob_flags = = VIRGL_RENDERER_BLOB_FLAG_USE_MAPPABLE ) {
int fd = alloc_memfd ( " proxy-blob " , blob_size , NULL ) ;
if ( fd < 0 )
return - ENOMEM ;
blob - > type = VIRGL_RESOURCE_FD_SHM ;
blob - > u . fd = fd ;
blob - > map_info = VIRGL_RENDERER_MAP_CACHE_CACHED ;
return 0 ;
}
const struct render_context_op_get_blob_request req = {
const struct render_context_op_get_blob_request req = {
. header . op = RENDER_CONTEXT_OP_GET_BLOB ,
. header . op = RENDER_CONTEXT_OP_GET_BLOB ,
. res_id = res_id ,
. res_id = res_id ,
@ -384,8 +373,8 @@ proxy_context_get_blob(struct virgl_context *base,
reply_fd_valid = true ;
reply_fd_valid = true ;
break ;
break ;
case VIRGL_RESOURCE_FD_SHM :
case VIRGL_RESOURCE_FD_SHM :
/* we don't expect shm, otherwise we should validate seals and size */
/* validate the seals and size her e */
reply_fd_valid = fals e ;
reply_fd_valid = validate_resource_ fd_shm ( r eply_fd , blob_size ) ;
break ;
break ;
default :
default :
break ;
break ;
@ -581,6 +570,32 @@ proxy_context_init_timelines(struct proxy_context *ctx)
return true ;
return true ;
}
}
static int
alloc_memfd ( const char * name , size_t size , void * * out_ptr )
{
int fd = os_create_anonymous_file ( size , name ) ;
if ( fd < 0 )
return - 1 ;
int ret = fcntl ( fd , F_ADD_SEALS , F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW ) ;
if ( ret )
goto fail ;
if ( ! out_ptr )
return fd ;
void * ptr = mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 ) ;
if ( ptr = = MAP_FAILED )
goto fail ;
* out_ptr = ptr ;
return fd ;
fail :
close ( fd ) ;
return - 1 ;
}
static bool
static bool
proxy_context_init_shmem ( struct proxy_context * ctx )
proxy_context_init_shmem ( struct proxy_context * ctx )
{
{