@ -13,7 +13,6 @@
# include <sys/resource.h>
# include <getopt.h>
# include <syslog.h>
# include <sys/capability.h>
# include <sys/fsuid.h>
# include <sys/vfs.h>
# include <sys/ioctl.h>
@ -21,6 +20,7 @@
# ifdef CONFIG_LINUX_MAGIC_H
# include <linux/magic.h>
# endif
# include <cap-ng.h>
# include "qemu-common.h"
# include "qemu/sockets.h"
# include "qemu/xattr.h"
@ -79,49 +79,10 @@ static void do_perror(const char *string)
}
}
static int do_cap_set ( cap_value_t * cap_value , int size , int reset )
{
cap_t caps ;
if ( reset ) {
/*
* Start with an empty set and set permitted and effective
*/
caps = cap_init ( ) ;
if ( caps = = NULL ) {
do_perror ( " cap_init " ) ;
return - 1 ;
}
if ( cap_set_flag ( caps , CAP_PERMITTED , size , cap_value , CAP_SET ) < 0 ) {
do_perror ( " cap_set_flag " ) ;
goto error ;
}
} else {
caps = cap_get_proc ( ) ;
if ( ! caps ) {
do_perror ( " cap_get_proc " ) ;
return - 1 ;
}
}
if ( cap_set_flag ( caps , CAP_EFFECTIVE , size , cap_value , CAP_SET ) < 0 ) {
do_perror ( " cap_set_flag " ) ;
goto error ;
}
if ( cap_set_proc ( caps ) < 0 ) {
do_perror ( " cap_set_proc " ) ;
goto error ;
}
cap_free ( caps ) ;
return 0 ;
error :
cap_free ( caps ) ;
return - 1 ;
}
static int init_capabilities ( void )
{
/* helper needs following capabilities only */
cap_value_ t cap_list [ ] = {
int cap_list [ ] = {
CAP_CHOWN ,
CAP_DAC_OVERRIDE ,
CAP_FOWNER ,
@ -130,7 +91,34 @@ static int init_capabilities(void)
CAP_MKNOD ,
CAP_SETUID ,
} ;
return do_cap_set ( cap_list , ARRAY_SIZE ( cap_list ) , 1 ) ;
int i ;
capng_clear ( CAPNG_SELECT_BOTH ) ;
for ( i = 0 ; i < ARRAY_SIZE ( cap_list ) ; i + + ) {
if ( capng_update ( CAPNG_ADD , CAPNG_EFFECTIVE | CAPNG_PERMITTED ,
cap_list [ i ] ) < 0 ) {
do_perror ( " capng_update " ) ;
return - 1 ;
}
}
if ( capng_apply ( CAPNG_SELECT_BOTH ) < 0 ) {
do_perror ( " capng_apply " ) ;
return - 1 ;
}
/* Prepare effective set for setugid. */
for ( i = 0 ; i < ARRAY_SIZE ( cap_list ) ; i + + ) {
if ( cap_list [ i ] = = CAP_DAC_OVERRIDE ) {
continue ;
}
if ( capng_update ( CAPNG_DROP , CAPNG_EFFECTIVE ,
cap_list [ i ] ) < 0 ) {
do_perror ( " capng_update " ) ;
return - 1 ;
}
}
return 0 ;
}
static int socket_read ( int sockfd , void * buff , ssize_t size )
@ -295,14 +283,6 @@ static int setugid(int uid, int gid, int *suid, int *sgid)
{
int retval ;
/*
* We still need DAC_OVERRIDE because we don ' t change
* supplementary group ids , and hence may be subjected DAC rules
*/
cap_value_t cap_list [ ] = {
CAP_DAC_OVERRIDE ,
} ;
* suid = geteuid ( ) ;
* sgid = getegid ( ) ;
@ -316,11 +296,21 @@ static int setugid(int uid, int gid, int *suid, int *sgid)
goto err_sgid ;
}
if ( uid ! = 0 | | gid ! = 0 ) {
if ( do_cap_set ( cap_list , ARRAY_SIZE ( cap_list ) , 0 ) < 0 ) {
retval = - errno ;
goto err_suid ;
}
if ( uid = = 0 & & gid = = 0 ) {
/* Linux has already copied the permitted set to the effective set. */
return 0 ;
}
/*
* All capabilities have been cleared from the effective set . However
* we still need DAC_OVERRIDE because we don ' t change supplementary
* group ids , and hence may be subject to DAC rules . init_capabilities
* left the set of capabilities that we want in libcap - ng ' s state .
*/
if ( capng_apply ( CAPNG_SELECT_CAPS ) < 0 ) {
retval = - errno ;
do_perror ( " capng_apply " ) ;
goto err_suid ;
}
return 0 ;