2015-03-23 11:17:58 +00:00
/*
* Copyright © 2014 Red Hat , Inc
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2016-07-29 18:27:49 +00:00
* version 2.1 of the License , or ( at your option ) any later version .
2015-03-23 11:17:58 +00:00
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see < http : //www.gnu.org/licenses/>.
*
* Authors :
* Alexander Larsson < alexl @ redhat . com >
*/
2015-02-13 09:29:41 +00:00
# include "config.h"
# include <string.h>
# include <fcntl.h>
# include <stdio.h>
2015-03-04 13:40:17 +00:00
# include <unistd.h>
2015-10-01 19:23:23 +00:00
# include <sys/utsname.h>
2016-04-29 09:39:39 +00:00
# include <sys/socket.h>
# include <grp.h>
# ifdef ENABLE_SECCOMP
# include <seccomp.h>
# endif
2015-10-01 19:23:23 +00:00
2016-01-28 13:34:22 +00:00
# ifdef ENABLE_XAUTH
2015-10-01 19:23:23 +00:00
# include <X11/Xauth.h>
2016-01-28 13:34:22 +00:00
# endif
2015-02-13 09:29:41 +00:00
2016-07-23 15:01:50 +00:00
# include <glib/gi18n.h>
2015-02-13 09:29:41 +00:00
# include <gio/gio.h>
2015-03-20 15:21:19 +00:00
# include "libglnx/libglnx.h"
2015-02-13 09:29:41 +00:00
2016-05-06 16:03:47 +00:00
# include "flatpak-run.h"
# include "flatpak-proxy.h"
# include "flatpak-utils.h"
# include "flatpak-systemd-dbus.h"
2015-02-13 09:29:41 +00:00
2016-04-29 09:39:39 +00:00
# define DEFAULT_SHELL " / bin / sh"
2015-10-01 19:23:23 +00:00
2015-05-22 13:36:52 +00:00
typedef enum {
2016-05-06 14:37:47 +00:00
FLATPAK_CONTEXT_SHARED_NETWORK = 1 < < 0 ,
FLATPAK_CONTEXT_SHARED_IPC = 1 < < 1 ,
} FlatpakContextShares ;
2015-05-22 13:36:52 +00:00
2016-04-29 09:39:39 +00:00
/* In numerical order of more privs */
2015-11-26 16:22:37 +00:00
typedef enum {
2016-05-06 14:37:47 +00:00
FLATPAK_FILESYSTEM_MODE_READ_ONLY = 1 ,
FLATPAK_FILESYSTEM_MODE_READ_WRITE = 2 ,
} FlatpakFilesystemMode ;
2015-11-26 16:22:37 +00:00
2015-09-09 12:11:05 +00:00
/* Same order as enum */
2016-05-27 14:30:13 +00:00
const char * flatpak_context_shares [ ] = {
2015-09-09 12:11:05 +00:00
" network " ,
" ipc " ,
NULL
} ;
2015-05-22 13:36:52 +00:00
typedef enum {
2016-05-06 14:37:47 +00:00
FLATPAK_CONTEXT_SOCKET_X11 = 1 < < 0 ,
FLATPAK_CONTEXT_SOCKET_WAYLAND = 1 < < 1 ,
FLATPAK_CONTEXT_SOCKET_PULSEAUDIO = 1 < < 2 ,
FLATPAK_CONTEXT_SOCKET_SESSION_BUS = 1 < < 3 ,
FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS = 1 < < 4 ,
} FlatpakContextSockets ;
2015-05-22 13:36:52 +00:00
2015-09-09 12:11:05 +00:00
/* Same order as enum */
2016-05-27 14:30:13 +00:00
const char * flatpak_context_sockets [ ] = {
2015-09-09 12:11:05 +00:00
" x11 " ,
" wayland " ,
" pulseaudio " ,
" session-bus " ,
" system-bus " ,
NULL
} ;
2016-04-29 09:39:39 +00:00
const char * dont_mount_in_root [ ] = {
" . " , " .. " , " lib " , " lib32 " , " lib64 " , " bin " , " sbin " , " usr " , " boot " , " root " ,
" tmp " , " etc " , " app " , " run " , " proc " , " sys " , " dev " , " var " , NULL
} ;
2015-05-22 13:36:52 +00:00
typedef enum {
2016-05-06 14:37:47 +00:00
FLATPAK_CONTEXT_DEVICE_DRI = 1 < < 0 ,
2016-06-14 20:33:14 +00:00
FLATPAK_CONTEXT_DEVICE_ALL = 1 < < 1 ,
2016-05-06 14:37:47 +00:00
} FlatpakContextDevices ;
2015-05-22 13:36:52 +00:00
2016-05-27 14:30:13 +00:00
const char * flatpak_context_devices [ ] = {
2015-09-09 12:11:05 +00:00
" dri " ,
2016-06-14 20:33:14 +00:00
" all " ,
2015-09-09 12:11:05 +00:00
NULL
} ;
2016-05-06 14:37:47 +00:00
struct FlatpakContext
{
FlatpakContextShares shares ;
FlatpakContextShares shares_valid ;
FlatpakContextSockets sockets ;
FlatpakContextSockets sockets_valid ;
FlatpakContextDevices devices ;
FlatpakContextDevices devices_valid ;
GHashTable * env_vars ;
GHashTable * persistent ;
GHashTable * filesystems ;
GHashTable * session_bus_policy ;
GHashTable * system_bus_policy ;
2015-05-22 13:36:52 +00:00
} ;
2016-05-06 14:37:47 +00:00
FlatpakContext *
flatpak_context_new ( void )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
context = g_slice_new0 ( FlatpakContext ) ;
2015-05-22 13:36:52 +00:00
context - > env_vars = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , g_free ) ;
context - > persistent = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , NULL ) ;
context - > filesystems = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , NULL ) ;
2016-01-29 07:50:11 +00:00
context - > session_bus_policy = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , NULL ) ;
context - > system_bus_policy = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , NULL ) ;
2015-05-22 13:36:52 +00:00
return context ;
}
void
2016-05-06 14:37:47 +00:00
flatpak_context_free ( FlatpakContext * context )
2015-05-22 13:36:52 +00:00
{
g_hash_table_destroy ( context - > env_vars ) ;
g_hash_table_destroy ( context - > persistent ) ;
g_hash_table_destroy ( context - > filesystems ) ;
2016-01-29 07:50:11 +00:00
g_hash_table_destroy ( context - > session_bus_policy ) ;
g_hash_table_destroy ( context - > system_bus_policy ) ;
2016-05-06 14:37:47 +00:00
g_slice_free ( FlatpakContext , context ) ;
2015-05-22 13:36:52 +00:00
}
2015-09-09 12:11:05 +00:00
static guint32
2016-05-06 14:37:47 +00:00
flatpak_context_bitmask_from_string ( const char * name , const char * * names )
2015-05-22 13:36:52 +00:00
{
2015-09-09 12:11:05 +00:00
guint32 i ;
for ( i = 0 ; names [ i ] ! = NULL ; i + + )
{
if ( strcmp ( names [ i ] , name ) = = 0 )
return 1 < < i ;
}
2015-05-22 13:36:52 +00:00
return 0 ;
}
static char * *
2016-05-06 14:37:47 +00:00
flatpak_context_bitmask_to_string ( guint32 enabled , guint32 valid , const char * * names )
2015-05-22 13:36:52 +00:00
{
2015-09-09 12:11:05 +00:00
guint32 i ;
2015-05-22 13:36:52 +00:00
GPtrArray * array ;
array = g_ptr_array_new ( ) ;
2015-09-09 12:11:05 +00:00
for ( i = 0 ; names [ i ] ! = NULL ; i + + )
{
guint32 bitmask = 1 < < i ;
if ( valid & bitmask )
{
if ( enabled & bitmask )
g_ptr_array_add ( array , g_strdup ( names [ i ] ) ) ;
else
g_ptr_array_add ( array , g_strdup_printf ( " !%s " , names [ i ] ) ) ;
}
}
2015-05-22 13:36:52 +00:00
g_ptr_array_add ( array , NULL ) ;
2016-05-06 14:03:27 +00:00
return ( char * * ) g_ptr_array_free ( array , FALSE ) ;
2015-05-22 13:36:52 +00:00
}
2016-05-26 10:23:48 +00:00
static void
flatpak_context_bitmask_to_args ( guint32 enabled , guint32 valid , const char * * names ,
const char * enable_arg , const char * disable_arg ,
GPtrArray * args )
{
guint32 i ;
for ( i = 0 ; names [ i ] ! = NULL ; i + + )
{
guint32 bitmask = 1 < < i ;
if ( valid & bitmask )
{
if ( enabled & bitmask )
g_ptr_array_add ( args , g_strdup_printf ( " %s=%s " , enable_arg , names [ i ] ) ) ;
else
g_ptr_array_add ( args , g_strdup_printf ( " %s=%s " , disable_arg , names [ i ] ) ) ;
}
}
}
2016-05-06 14:37:47 +00:00
static FlatpakContextShares
flatpak_context_share_from_string ( const char * string , GError * * error )
2015-09-09 12:11:05 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContextShares shares = flatpak_context_bitmask_from_string ( string , flatpak_context_shares ) ;
2015-09-09 12:11:05 +00:00
if ( shares = = 0 )
2016-07-23 19:02:01 +00:00
{
g_autofree char * values = g_strjoinv ( " , " , ( char * * ) flatpak_context_shares ) ;
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
_ ( " Unknown share type %s, valid types are: %s " ) , string , values ) ;
}
2015-09-09 12:11:05 +00:00
return shares ;
}
static char * *
2016-05-06 14:37:47 +00:00
flatpak_context_shared_to_string ( FlatpakContextShares shares , FlatpakContextShares valid )
2015-09-09 12:11:05 +00:00
{
2016-05-06 14:37:47 +00:00
return flatpak_context_bitmask_to_string ( shares , valid , flatpak_context_shares ) ;
2015-09-09 12:11:05 +00:00
}
2016-05-26 10:23:48 +00:00
static void
flatpak_context_shared_to_args ( FlatpakContextShares shares ,
FlatpakContextShares valid ,
GPtrArray * args )
{
return flatpak_context_bitmask_to_args ( shares , valid , flatpak_context_shares , " --share " , " --unshare " , args ) ;
}
2016-05-06 14:37:47 +00:00
static FlatpakPolicy
flatpak_policy_from_string ( const char * string , GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-07-23 19:02:01 +00:00
const char * policies [ ] = { " none " , " see " , " talk " , " own " , NULL } ;
int i ;
g_autofree char * values = NULL ;
for ( i = 0 ; policies [ i ] ; i + + )
{
if ( strcmp ( string , policies [ i ] ) = = 0 )
return i ;
}
2015-05-22 13:36:52 +00:00
2016-07-23 19:02:01 +00:00
values = g_strjoinv ( " , " , ( char * * ) policies ) ;
2015-05-22 13:36:52 +00:00
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
2016-07-23 19:02:01 +00:00
_ ( " Unknown policy type %s, valid types are: %s " ) , string , values ) ;
2015-05-22 13:36:52 +00:00
return - 1 ;
}
static const char *
2016-05-06 14:37:47 +00:00
flatpak_policy_to_string ( FlatpakPolicy policy )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
if ( policy = = FLATPAK_POLICY_SEE )
2015-05-22 13:36:52 +00:00
return " see " ;
2016-05-06 14:37:47 +00:00
if ( policy = = FLATPAK_POLICY_TALK )
2015-05-22 13:36:52 +00:00
return " talk " ;
2016-05-06 14:37:47 +00:00
if ( policy = = FLATPAK_POLICY_OWN )
2015-05-22 13:36:52 +00:00
return " own " ;
return " none " ;
}
static gboolean
2016-05-06 14:37:47 +00:00
flatpak_verify_dbus_name ( const char * name , GError * * error )
2015-05-22 13:36:52 +00:00
{
const char * name_part ;
g_autofree char * tmp = NULL ;
if ( g_str_has_suffix ( name , " .* " ) )
{
tmp = g_strndup ( name , strlen ( name ) - 2 ) ;
name_part = tmp ;
}
else
2016-05-06 14:03:27 +00:00
{
name_part = name ;
}
2015-05-22 13:36:52 +00:00
if ( g_dbus_is_name ( name_part ) & & ! g_dbus_is_unique_name ( name_part ) )
return TRUE ;
2016-07-23 17:59:45 +00:00
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
_ ( " Invalid dbus name %s \n " ) , name ) ;
2015-05-22 13:36:52 +00:00
return FALSE ;
}
2016-05-06 14:37:47 +00:00
static FlatpakContextSockets
flatpak_context_socket_from_string ( const char * string , GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContextSockets sockets = flatpak_context_bitmask_from_string ( string , flatpak_context_sockets ) ;
2015-05-22 13:36:52 +00:00
2015-09-09 12:11:05 +00:00
if ( sockets = = 0 )
2016-07-23 19:02:01 +00:00
{
g_autofree char * values = g_strjoinv ( " , " , ( char * * ) flatpak_context_sockets ) ;
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
_ ( " Unknown socket type %s, valid types are: %s " ) , string , values ) ;
}
2015-09-09 12:11:05 +00:00
return sockets ;
2015-05-22 13:36:52 +00:00
}
static char * *
2016-05-06 14:37:47 +00:00
flatpak_context_sockets_to_string ( FlatpakContextSockets sockets , FlatpakContextSockets valid )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
return flatpak_context_bitmask_to_string ( sockets , valid , flatpak_context_sockets ) ;
2015-05-22 13:36:52 +00:00
}
2016-05-26 10:23:48 +00:00
static void
flatpak_context_sockets_to_args ( FlatpakContextSockets sockets ,
FlatpakContextSockets valid ,
GPtrArray * args )
{
return flatpak_context_bitmask_to_args ( sockets , valid , flatpak_context_sockets , " --socket " , " --nosocket " , args ) ;
}
2016-05-06 14:37:47 +00:00
static FlatpakContextDevices
flatpak_context_device_from_string ( const char * string , GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContextDevices devices = flatpak_context_bitmask_from_string ( string , flatpak_context_devices ) ;
2015-05-22 13:36:52 +00:00
2015-09-09 12:11:05 +00:00
if ( devices = = 0 )
2016-07-23 19:02:01 +00:00
{
g_autofree char * values = g_strjoinv ( " , " , ( char * * ) flatpak_context_devices ) ;
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
_ ( " Unknown device type %s, valid types are: %s " ) , string , values ) ;
}
2015-09-09 12:11:05 +00:00
return devices ;
2015-05-22 13:36:52 +00:00
}
static char * *
2016-05-06 14:37:47 +00:00
flatpak_context_devices_to_string ( FlatpakContextDevices devices , FlatpakContextDevices valid )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
return flatpak_context_bitmask_to_string ( devices , valid , flatpak_context_devices ) ;
2015-05-22 13:36:52 +00:00
}
2016-05-26 10:23:48 +00:00
static void
flatpak_context_devices_to_args ( FlatpakContextDevices devices ,
FlatpakContextDevices valid ,
GPtrArray * args )
{
return flatpak_context_bitmask_to_args ( devices , valid , flatpak_context_devices , " --device " , " --nodevice " , args ) ;
}
2015-05-22 13:36:52 +00:00
static void
2016-05-06 14:37:47 +00:00
flatpak_context_add_shares ( FlatpakContext * context ,
FlatpakContextShares shares )
2015-05-22 13:36:52 +00:00
{
context - > shares_valid | = shares ;
context - > shares | = shares ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_remove_shares ( FlatpakContext * context ,
FlatpakContextShares shares )
2015-05-22 13:36:52 +00:00
{
context - > shares_valid | = shares ;
context - > shares & = ~ shares ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_add_sockets ( FlatpakContext * context ,
FlatpakContextSockets sockets )
2015-05-22 13:36:52 +00:00
{
context - > sockets_valid | = sockets ;
context - > sockets | = sockets ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_remove_sockets ( FlatpakContext * context ,
FlatpakContextSockets sockets )
2015-05-22 13:36:52 +00:00
{
context - > sockets_valid | = sockets ;
context - > sockets & = ~ sockets ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_add_devices ( FlatpakContext * context ,
FlatpakContextDevices devices )
2015-05-22 13:36:52 +00:00
{
context - > devices_valid | = devices ;
context - > devices | = devices ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_remove_devices ( FlatpakContext * context ,
FlatpakContextDevices devices )
2015-05-22 13:36:52 +00:00
{
context - > devices_valid | = devices ;
context - > devices & = ~ devices ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_set_env_var ( FlatpakContext * context ,
const char * name ,
const char * value )
2015-05-22 13:36:52 +00:00
{
g_hash_table_insert ( context - > env_vars , g_strdup ( name ) , g_strdup ( value ) ) ;
}
2015-10-21 10:18:13 +00:00
void
2016-05-06 14:37:47 +00:00
flatpak_context_set_session_bus_policy ( FlatpakContext * context ,
const char * name ,
FlatpakPolicy policy )
2015-05-22 13:36:52 +00:00
{
2016-01-29 07:50:11 +00:00
g_hash_table_insert ( context - > session_bus_policy , g_strdup ( name ) , GINT_TO_POINTER ( policy ) ) ;
}
void
2016-05-06 14:37:47 +00:00
flatpak_context_set_system_bus_policy ( FlatpakContext * context ,
const char * name ,
FlatpakPolicy policy )
2016-01-29 07:50:11 +00:00
{
g_hash_table_insert ( context - > system_bus_policy , g_strdup ( name ) , GINT_TO_POINTER ( policy ) ) ;
2015-05-22 13:36:52 +00:00
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_set_persistent ( FlatpakContext * context ,
const char * path )
2015-05-22 13:36:52 +00:00
{
g_hash_table_insert ( context - > persistent , g_strdup ( path ) , GINT_TO_POINTER ( 1 ) ) ;
}
2016-04-20 12:26:03 +00:00
static gboolean
2016-05-06 14:03:27 +00:00
get_user_dir_from_string ( const char * filesystem ,
2016-02-25 16:11:37 +00:00
const char * * config_key ,
2016-04-20 12:26:03 +00:00
const char * * suffix ,
const char * * dir )
2015-05-25 13:28:29 +00:00
{
2016-02-25 15:51:45 +00:00
char * slash ;
2016-02-25 16:11:37 +00:00
const char * rest ;
2016-02-25 15:51:45 +00:00
g_autofree char * prefix ;
gsize len ;
slash = strchr ( filesystem , ' / ' ) ;
if ( slash )
len = slash - filesystem ;
else
len = strlen ( filesystem ) ;
2016-02-25 16:11:37 +00:00
rest = filesystem + len ;
while ( * rest = = ' / ' )
2016-05-06 14:03:27 +00:00
rest + + ;
2016-02-25 16:11:37 +00:00
2016-02-25 15:51:45 +00:00
if ( suffix )
2016-02-25 16:11:37 +00:00
* suffix = rest ;
2016-02-25 15:51:45 +00:00
prefix = g_strndup ( filesystem , len ) ;
if ( strcmp ( prefix , " xdg-desktop " ) = = 0 )
2016-02-25 16:11:37 +00:00
{
if ( config_key )
* config_key = " XDG_DESKTOP_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_DESKTOP ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
2016-02-25 15:51:45 +00:00
if ( strcmp ( prefix , " xdg-documents " ) = = 0 )
2016-02-25 16:11:37 +00:00
{
if ( config_key )
* config_key = " XDG_DOCUMENTS_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_DOCUMENTS ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
2016-02-25 15:51:45 +00:00
if ( strcmp ( prefix , " xdg-download " ) = = 0 )
2016-02-25 16:11:37 +00:00
{
if ( config_key )
* config_key = " XDG_DOWNLOAD_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_DOWNLOAD ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
if ( strcmp ( prefix , " xdg-music " ) = = 0 )
{
if ( config_key )
* config_key = " XDG_MUSIC_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_MUSIC ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
if ( strcmp ( prefix , " xdg-pictures " ) = = 0 )
{
if ( config_key )
* config_key = " XDG_PICTURES_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_PICTURES ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
if ( strcmp ( prefix , " xdg-public-share " ) = = 0 )
{
if ( config_key )
* config_key = " XDG_PUBLICSHARE_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_PUBLIC_SHARE ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
if ( strcmp ( prefix , " xdg-templates " ) = = 0 )
{
if ( config_key )
* config_key = " XDG_TEMPLATES_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_TEMPLATES ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
if ( strcmp ( prefix , " xdg-videos " ) = = 0 )
{
if ( config_key )
* config_key = " XDG_VIDEOS_DIR " ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_special_dir ( G_USER_DIRECTORY_VIDEOS ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
/* Don't support xdg-run without suffix, because that doesn't work */
if ( strcmp ( prefix , " xdg-run " ) = = 0 & &
* rest ! = 0 )
{
if ( config_key )
* config_key = NULL ;
2016-04-20 12:26:03 +00:00
if ( dir )
* dir = g_get_user_runtime_dir ( ) ;
return TRUE ;
2016-02-25 16:11:37 +00:00
}
2015-05-25 13:28:29 +00:00
2016-04-21 07:39:55 +00:00
return FALSE ;
2015-05-25 13:28:29 +00:00
}
2015-11-26 16:22:37 +00:00
static char *
2016-05-06 14:37:47 +00:00
parse_filesystem_flags ( const char * filesystem , FlatpakFilesystemMode * mode )
2015-11-26 16:22:37 +00:00
{
gsize len = strlen ( filesystem ) ;
if ( mode )
2016-05-06 14:37:47 +00:00
* mode = FLATPAK_FILESYSTEM_MODE_READ_WRITE ;
2015-11-26 16:22:37 +00:00
if ( g_str_has_suffix ( filesystem , " :ro " ) )
{
len - = 3 ;
if ( mode )
2016-05-06 14:37:47 +00:00
* mode = FLATPAK_FILESYSTEM_MODE_READ_ONLY ;
2015-11-26 16:22:37 +00:00
}
else if ( g_str_has_suffix ( filesystem , " :rw " ) )
{
len - = 3 ;
if ( mode )
2016-05-06 14:37:47 +00:00
* mode = FLATPAK_FILESYSTEM_MODE_READ_WRITE ;
2015-11-26 16:22:37 +00:00
}
return g_strndup ( filesystem , len ) ;
}
2015-05-22 13:36:52 +00:00
static gboolean
2016-05-06 14:37:47 +00:00
flatpak_context_verify_filesystem ( const char * filesystem_and_mode ,
2016-05-06 14:03:27 +00:00
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-02-25 15:51:45 +00:00
g_autofree char * filesystem = parse_filesystem_flags ( filesystem_and_mode , NULL ) ;
2015-11-26 16:22:37 +00:00
2015-05-22 13:36:52 +00:00
if ( strcmp ( filesystem , " host " ) = = 0 )
return TRUE ;
if ( strcmp ( filesystem , " home " ) = = 0 )
return TRUE ;
2016-04-20 12:26:03 +00:00
if ( get_user_dir_from_string ( filesystem , NULL , NULL , NULL ) )
2015-05-22 13:36:52 +00:00
return TRUE ;
if ( g_str_has_prefix ( filesystem , " ~/ " ) )
return TRUE ;
if ( g_str_has_prefix ( filesystem , " / " ) )
return TRUE ;
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
2016-07-23 19:02:01 +00:00
_ ( " Unknown filesystem location %s, valid types are: host, home, xdg-*[/...], ~/dir, /dir " ) , filesystem ) ;
2015-05-22 13:36:52 +00:00
return FALSE ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_context_add_filesystem ( FlatpakContext * context ,
const char * what )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakFilesystemMode mode ;
2015-11-26 16:22:37 +00:00
char * fs = parse_filesystem_flags ( what , & mode ) ;
g_hash_table_insert ( context - > filesystems , fs , GINT_TO_POINTER ( mode ) ) ;
2015-05-22 13:36:52 +00:00
}
2015-09-09 12:11:05 +00:00
static void
2016-05-06 14:37:47 +00:00
flatpak_context_remove_filesystem ( FlatpakContext * context ,
const char * what )
2015-09-09 12:11:05 +00:00
{
2015-11-26 16:22:37 +00:00
g_hash_table_insert ( context - > filesystems ,
parse_filesystem_flags ( what , NULL ) ,
NULL ) ;
2015-09-09 12:11:05 +00:00
}
2015-05-22 13:36:52 +00:00
void
2016-05-06 14:37:47 +00:00
flatpak_context_merge ( FlatpakContext * context ,
FlatpakContext * other )
2015-05-22 13:36:52 +00:00
{
GHashTableIter iter ;
gpointer key , value ;
context - > shares & = ~ other - > shares_valid ;
context - > shares | = other - > shares ;
2015-09-09 12:11:05 +00:00
context - > shares_valid | = other - > shares_valid ;
2015-05-22 13:36:52 +00:00
context - > sockets & = ~ other - > sockets_valid ;
context - > sockets | = other - > sockets ;
2015-09-09 12:11:05 +00:00
context - > sockets_valid | = other - > sockets_valid ;
2015-05-22 13:36:52 +00:00
context - > devices & = ~ other - > devices_valid ;
context - > devices | = other - > devices ;
2015-09-09 12:11:05 +00:00
context - > devices_valid | = other - > devices_valid ;
2015-05-22 13:36:52 +00:00
g_hash_table_iter_init ( & iter , other - > env_vars ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_hash_table_insert ( context - > env_vars , g_strdup ( key ) , g_strdup ( value ) ) ;
g_hash_table_iter_init ( & iter , other - > persistent ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_hash_table_insert ( context - > persistent , g_strdup ( key ) , value ) ;
g_hash_table_iter_init ( & iter , other - > filesystems ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_hash_table_insert ( context - > filesystems , g_strdup ( key ) , value ) ;
2016-01-29 07:50:11 +00:00
g_hash_table_iter_init ( & iter , other - > session_bus_policy ) ;
2015-05-22 13:36:52 +00:00
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
2016-01-29 07:50:11 +00:00
g_hash_table_insert ( context - > session_bus_policy , g_strdup ( key ) , value ) ;
g_hash_table_iter_init ( & iter , other - > system_bus_policy ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_hash_table_insert ( context - > system_bus_policy , g_strdup ( key ) , value ) ;
2015-05-22 13:36:52 +00:00
}
static gboolean
2016-05-06 14:03:27 +00:00
option_share_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextShares share ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
share = flatpak_context_share_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( share = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_add_shares ( context , share ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_unshare_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextShares share ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
share = flatpak_context_share_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( share = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_remove_shares ( context , share ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_socket_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextSockets socket ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
socket = flatpak_context_socket_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( socket = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_add_sockets ( context , socket ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_nosocket_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextSockets socket ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
socket = flatpak_context_socket_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( socket = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_remove_sockets ( context , socket ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_device_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextDevices device ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
device = flatpak_context_device_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( device = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_add_devices ( context , device ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_nodevice_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
FlatpakContextDevices device ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
device = flatpak_context_device_from_string ( value , error ) ;
2015-05-22 13:36:52 +00:00
if ( device = = 0 )
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_remove_devices ( context , device ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_filesystem_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_context_verify_filesystem ( value , error ) )
2015-05-22 13:36:52 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_add_filesystem ( context , value ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
2015-09-25 15:04:50 +00:00
static gboolean
2016-05-06 14:03:27 +00:00
option_nofilesystem_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-09-25 15:04:50 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2015-09-25 15:04:50 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_context_verify_filesystem ( value , error ) )
2015-09-25 15:04:50 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_remove_filesystem ( context , value ) ;
2015-09-25 15:04:50 +00:00
return TRUE ;
}
2015-05-22 13:36:52 +00:00
static gboolean
2016-05-06 14:03:27 +00:00
option_env_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2016-05-06 14:03:27 +00:00
2015-08-31 07:51:48 +00:00
g_auto ( GStrv ) split = g_strsplit ( value , " = " , 2 ) ;
2015-05-22 13:36:52 +00:00
if ( split = = NULL | | split [ 0 ] = = NULL | | split [ 0 ] [ 0 ] = = 0 | | split [ 1 ] = = NULL )
{
2016-07-23 17:59:45 +00:00
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_FAILED ,
_ ( " Invalid env format %s " ) , value ) ;
2015-05-22 13:36:52 +00:00
return FALSE ;
}
2016-05-06 14:37:47 +00:00
flatpak_context_set_env_var ( context , split [ 0 ] , split [ 1 ] ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_own_name_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( value , error ) )
2015-05-22 13:36:52 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_session_bus_policy ( context , value , FLATPAK_POLICY_OWN ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_talk_name_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( value , error ) )
2015-05-22 13:36:52 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_session_bus_policy ( context , value , FLATPAK_POLICY_TALK ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
2016-01-29 07:50:11 +00:00
static gboolean
2016-05-06 14:03:27 +00:00
option_system_own_name_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2016-01-29 07:50:11 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2016-01-29 07:50:11 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( value , error ) )
2016-01-29 07:50:11 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_system_bus_policy ( context , value , FLATPAK_POLICY_OWN ) ;
2016-01-29 07:50:11 +00:00
return TRUE ;
}
static gboolean
2016-05-06 14:03:27 +00:00
option_system_talk_name_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2016-01-29 07:50:11 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2016-01-29 07:50:11 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( value , error ) )
2016-01-29 07:50:11 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_system_bus_policy ( context , value , FLATPAK_POLICY_TALK ) ;
2016-01-29 07:50:11 +00:00
return TRUE ;
}
2015-05-22 13:36:52 +00:00
static gboolean
2016-05-06 14:03:27 +00:00
option_persist_cb ( const gchar * option_name ,
const gchar * value ,
gpointer data ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakContext * context = data ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
flatpak_context_set_persistent ( context , value ) ;
2015-05-22 13:36:52 +00:00
return TRUE ;
}
2016-07-01 17:33:53 +00:00
static gboolean option_no_desktop ;
2015-05-22 13:36:52 +00:00
static GOptionEntry context_options [ ] = {
2016-07-23 15:01:50 +00:00
{ " share " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_share_cb , N_ ( " Share with host " ) , N_ ( " SHARE " ) } ,
{ " unshare " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_unshare_cb , N_ ( " Unshare with host " ) , N_ ( " SHARE " ) } ,
{ " socket " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_socket_cb , N_ ( " Expose socket to app " ) , N_ ( " SOCKET " ) } ,
{ " nosocket " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_nosocket_cb , N_ ( " Don't expose socket to app " ) , N_ ( " SOCKET " ) } ,
{ " device " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_device_cb , N_ ( " Expose device to app " ) , N_ ( " DEVICE " ) } ,
{ " nodevice " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_nodevice_cb , N_ ( " Don't expose device to app " ) , N_ ( " DEVICE " ) } ,
{ " filesystem " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_filesystem_cb , N_ ( " Expose filesystem to app (:ro for read-only) " ) , N_ ( " FILESYSTEM[:ro] " ) } ,
{ " nofilesystem " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_nofilesystem_cb , N_ ( " Don't expose filesystem to app " ) , N_ ( " FILESYSTEM " ) } ,
{ " env " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_env_cb , N_ ( " Set environment variable " ) , N_ ( " VAR=VALUE " ) } ,
{ " own-name " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_own_name_cb , N_ ( " Allow app to own name on the session bus " ) , N_ ( " DBUS_NAME " ) } ,
{ " talk-name " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_talk_name_cb , N_ ( " Allow app to talk to name on the session bus " ) , N_ ( " DBUS_NAME " ) } ,
{ " system-own-name " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_system_own_name_cb , N_ ( " Allow app to own name on the system bus " ) , N_ ( " DBUS_NAME " ) } ,
{ " system-talk-name " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_system_talk_name_cb , N_ ( " Allow app to talk to name on the system bus " ) , N_ ( " DBUS_NAME " ) } ,
{ " persist " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_CALLBACK , & option_persist_cb , N_ ( " Persist home directory " ) , N_ ( " FILENAME " ) } ,
{ " no-desktop " , 0 , G_OPTION_FLAG_IN_MAIN , G_OPTION_ARG_NONE , & option_no_desktop , N_ ( " Don't require a running session (no cgroups creation) " ) , NULL } ,
2015-05-22 13:36:52 +00:00
{ NULL }
} ;
2016-05-27 14:30:13 +00:00
void
flatpak_context_complete ( FlatpakContext * context , FlatpakCompletion * completion )
{
flatpak_complete_options ( completion , context_options ) ;
}
2015-05-22 13:36:52 +00:00
GOptionGroup *
2016-05-06 14:37:47 +00:00
flatpak_context_get_options ( FlatpakContext * context )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:03:27 +00:00
GOptionGroup * group ;
2015-05-22 13:36:52 +00:00
group = g_option_group_new ( " environment " ,
" Runtime Environment " ,
" Runtime Environment " ,
context ,
NULL ) ;
2016-07-23 15:01:50 +00:00
g_option_group_set_translation_domain ( group , GETTEXT_PACKAGE ) ;
2015-05-22 13:36:52 +00:00
g_option_group_add_entries ( group , context_options ) ;
return group ;
}
2015-09-09 12:11:05 +00:00
static const char *
parse_negated ( const char * option , gboolean * negated )
{
if ( option [ 0 ] = = ' ! ' )
{
option + + ;
* negated = TRUE ;
}
else
2016-05-06 14:03:27 +00:00
{
* negated = FALSE ;
}
2015-09-09 12:11:05 +00:00
return option ;
}
2015-05-22 13:36:52 +00:00
/* This is a merge, not a replace */
gboolean
2016-05-06 14:37:47 +00:00
flatpak_context_load_metadata ( FlatpakContext * context ,
GKeyFile * metakey ,
GError * * error )
2015-05-22 13:36:52 +00:00
{
2015-09-09 12:11:05 +00:00
gboolean remove ;
2015-05-22 13:36:52 +00:00
int i ;
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_key ( metakey , FLATPAK_METADATA_GROUP_CONTEXT , FLATPAK_METADATA_KEY_SHARED , NULL ) )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) shares = g_key_file_get_string_list ( metakey , FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SHARED , NULL , error ) ;
2015-05-22 13:36:52 +00:00
if ( shares = = NULL )
return FALSE ;
for ( i = 0 ; shares [ i ] ! = NULL ; i + + )
{
2016-05-06 14:37:47 +00:00
FlatpakContextShares share ;
2015-09-09 12:11:05 +00:00
2016-05-06 14:37:47 +00:00
share = flatpak_context_share_from_string ( parse_negated ( shares [ i ] , & remove ) , error ) ;
2015-05-22 13:36:52 +00:00
if ( share = = 0 )
return FALSE ;
2015-09-09 12:11:05 +00:00
if ( remove )
2016-05-06 14:37:47 +00:00
flatpak_context_remove_shares ( context , share ) ;
2015-09-09 12:11:05 +00:00
else
2016-05-06 14:37:47 +00:00
flatpak_context_add_shares ( context , share ) ;
2015-05-22 13:36:52 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_key ( metakey , FLATPAK_METADATA_GROUP_CONTEXT , FLATPAK_METADATA_KEY_SOCKETS , NULL ) )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) sockets = g_key_file_get_string_list ( metakey , FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SOCKETS , NULL , error ) ;
2015-05-22 13:36:52 +00:00
if ( sockets = = NULL )
return FALSE ;
for ( i = 0 ; sockets [ i ] ! = NULL ; i + + )
{
2016-05-06 14:37:47 +00:00
FlatpakContextSockets socket = flatpak_context_socket_from_string ( parse_negated ( sockets [ i ] , & remove ) , error ) ;
2015-05-22 13:36:52 +00:00
if ( socket = = 0 )
return FALSE ;
2015-09-09 12:11:05 +00:00
if ( remove )
2016-05-06 14:37:47 +00:00
flatpak_context_remove_sockets ( context , socket ) ;
2015-09-09 12:11:05 +00:00
else
2016-05-06 14:37:47 +00:00
flatpak_context_add_sockets ( context , socket ) ;
2015-05-22 13:36:52 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_key ( metakey , FLATPAK_METADATA_GROUP_CONTEXT , FLATPAK_METADATA_KEY_DEVICES , NULL ) )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) devices = g_key_file_get_string_list ( metakey , FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_DEVICES , NULL , error ) ;
2015-05-22 13:36:52 +00:00
if ( devices = = NULL )
return FALSE ;
for ( i = 0 ; devices [ i ] ! = NULL ; i + + )
{
2016-05-06 14:37:47 +00:00
FlatpakContextDevices device = flatpak_context_device_from_string ( parse_negated ( devices [ i ] , & remove ) , error ) ;
2015-05-22 13:36:52 +00:00
if ( device = = 0 )
return FALSE ;
2015-09-09 12:11:05 +00:00
if ( remove )
2016-05-06 14:37:47 +00:00
flatpak_context_remove_devices ( context , device ) ;
2015-09-09 12:11:05 +00:00
else
2016-05-06 14:37:47 +00:00
flatpak_context_add_devices ( context , device ) ;
2015-05-22 13:36:52 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_key ( metakey , FLATPAK_METADATA_GROUP_CONTEXT , FLATPAK_METADATA_KEY_FILESYSTEMS , NULL ) )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) filesystems = g_key_file_get_string_list ( metakey , FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_FILESYSTEMS , NULL , error ) ;
2015-05-22 13:36:52 +00:00
if ( filesystems = = NULL )
return FALSE ;
for ( i = 0 ; filesystems [ i ] ! = NULL ; i + + )
{
2015-09-09 12:11:05 +00:00
const char * fs = parse_negated ( filesystems [ i ] , & remove ) ;
2016-05-06 14:37:47 +00:00
if ( ! flatpak_context_verify_filesystem ( fs , error ) )
2015-05-22 13:36:52 +00:00
return FALSE ;
2015-09-09 12:11:05 +00:00
if ( remove )
2016-05-06 14:37:47 +00:00
flatpak_context_remove_filesystem ( context , fs ) ;
2015-09-23 11:53:04 +00:00
else
2016-05-06 14:37:47 +00:00
flatpak_context_add_filesystem ( context , fs ) ;
2015-05-22 13:36:52 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_key ( metakey , FLATPAK_METADATA_GROUP_CONTEXT , FLATPAK_METADATA_KEY_PERSISTENT , NULL ) )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) persistent = g_key_file_get_string_list ( metakey , FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_PERSISTENT , NULL , error ) ;
2015-05-22 13:36:52 +00:00
if ( persistent = = NULL )
return FALSE ;
for ( i = 0 ; persistent [ i ] ! = NULL ; i + + )
2016-05-06 14:37:47 +00:00
flatpak_context_set_persistent ( context , persistent [ i ] ) ;
2015-05-22 13:36:52 +00:00
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_group ( metakey , FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY ) )
2015-05-22 13:36:52 +00:00
{
2015-08-31 07:51:48 +00:00
g_auto ( GStrv ) keys = NULL ;
2015-05-22 13:36:52 +00:00
gsize i , keys_count ;
2016-05-06 14:37:47 +00:00
keys = g_key_file_get_keys ( metakey , FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY , & keys_count , NULL ) ;
2015-05-22 13:36:52 +00:00
for ( i = 0 ; i < keys_count ; i + + )
{
const char * key = keys [ i ] ;
2016-05-06 14:37:47 +00:00
g_autofree char * value = g_key_file_get_string ( metakey , FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY , key , NULL ) ;
FlatpakPolicy policy ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( key , error ) )
2015-05-22 13:36:52 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
policy = flatpak_policy_from_string ( value , error ) ;
2016-05-06 14:03:27 +00:00
if ( ( int ) policy = = - 1 )
2015-05-22 13:36:52 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_session_bus_policy ( context , key , policy ) ;
2015-05-22 13:36:52 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_group ( metakey , FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY ) )
2016-01-29 07:50:11 +00:00
{
g_auto ( GStrv ) keys = NULL ;
gsize i , keys_count ;
2016-05-06 14:37:47 +00:00
keys = g_key_file_get_keys ( metakey , FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY , & keys_count , NULL ) ;
2016-01-29 07:50:11 +00:00
for ( i = 0 ; i < keys_count ; i + + )
{
const char * key = keys [ i ] ;
2016-05-06 14:37:47 +00:00
g_autofree char * value = g_key_file_get_string ( metakey , FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY , key , NULL ) ;
FlatpakPolicy policy ;
2016-01-29 07:50:11 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_verify_dbus_name ( key , error ) )
2016-01-29 07:50:11 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
policy = flatpak_policy_from_string ( value , error ) ;
2016-05-06 14:03:27 +00:00
if ( ( int ) policy = = - 1 )
2016-01-29 07:50:11 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
flatpak_context_set_system_bus_policy ( context , key , policy ) ;
2016-01-29 07:50:11 +00:00
}
}
2016-05-06 14:37:47 +00:00
if ( g_key_file_has_group ( metakey , FLATPAK_METADATA_GROUP_ENVIRONMENT ) )
2015-05-22 13:36:52 +00:00
{
2015-08-31 07:51:48 +00:00
g_auto ( GStrv ) keys = NULL ;
2015-05-22 13:36:52 +00:00
gsize i , keys_count ;
2016-05-06 14:37:47 +00:00
keys = g_key_file_get_keys ( metakey , FLATPAK_METADATA_GROUP_ENVIRONMENT , & keys_count , NULL ) ;
2015-05-22 13:36:52 +00:00
for ( i = 0 ; i < keys_count ; i + + )
{
const char * key = keys [ i ] ;
2016-05-06 14:37:47 +00:00
g_autofree char * value = g_key_file_get_string ( metakey , FLATPAK_METADATA_GROUP_ENVIRONMENT , key , NULL ) ;
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
flatpak_context_set_env_var ( context , key , value ) ;
2015-05-22 13:36:52 +00:00
}
}
return TRUE ;
}
void
2016-05-06 14:37:47 +00:00
flatpak_context_save_metadata ( FlatpakContext * context ,
GKeyFile * metakey )
2015-05-22 13:36:52 +00:00
{
2016-05-06 14:37:47 +00:00
g_auto ( GStrv ) shared = flatpak_context_shared_to_string ( context - > shares , context - > shares_valid ) ;
g_auto ( GStrv ) sockets = flatpak_context_sockets_to_string ( context - > sockets , context - > sockets_valid ) ;
g_auto ( GStrv ) devices = flatpak_context_devices_to_string ( context - > devices , context - > devices_valid ) ;
2015-05-22 13:36:52 +00:00
GHashTableIter iter ;
gpointer key , value ;
if ( shared [ 0 ] ! = NULL )
2016-05-06 14:03:27 +00:00
{
g_key_file_set_string_list ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SHARED ,
2016-05-06 14:03:27 +00:00
( const char * const * ) shared , g_strv_length ( shared ) ) ;
}
2015-05-22 13:36:52 +00:00
else
2016-05-06 14:03:27 +00:00
{
g_key_file_remove_key ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SHARED ,
2016-05-06 14:03:27 +00:00
NULL ) ;
}
2015-05-22 13:36:52 +00:00
if ( sockets [ 0 ] ! = NULL )
2016-05-06 14:03:27 +00:00
{
g_key_file_set_string_list ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SOCKETS ,
2016-05-06 14:03:27 +00:00
( const char * const * ) sockets , g_strv_length ( sockets ) ) ;
}
2015-05-22 13:36:52 +00:00
else
2016-05-06 14:03:27 +00:00
{
g_key_file_remove_key ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_SOCKETS ,
2016-05-06 14:03:27 +00:00
NULL ) ;
}
2015-05-22 13:36:52 +00:00
if ( devices [ 0 ] ! = NULL )
2016-05-06 14:03:27 +00:00
{
g_key_file_set_string_list ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_DEVICES ,
2016-05-06 14:03:27 +00:00
( const char * const * ) devices , g_strv_length ( devices ) ) ;
}
2015-05-22 13:36:52 +00:00
else
2016-05-06 14:03:27 +00:00
{
g_key_file_remove_key ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_DEVICES ,
2016-05-06 14:03:27 +00:00
NULL ) ;
}
2015-05-22 13:36:52 +00:00
if ( g_hash_table_size ( context - > filesystems ) > 0 )
{
2015-11-26 16:22:37 +00:00
g_autoptr ( GPtrArray ) array = g_ptr_array_new_with_free_func ( g_free ) ;
2015-09-09 12:11:05 +00:00
g_hash_table_iter_init ( & iter , context - > filesystems ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
2016-05-06 14:37:47 +00:00
FlatpakFilesystemMode mode = GPOINTER_TO_INT ( value ) ;
2015-11-26 16:22:37 +00:00
2016-05-06 14:37:47 +00:00
if ( mode = = FLATPAK_FILESYSTEM_MODE_READ_ONLY )
2015-11-26 16:22:37 +00:00
g_ptr_array_add ( array , g_strconcat ( key , " :ro " , NULL ) ) ;
else if ( value ! = NULL )
g_ptr_array_add ( array , g_strdup ( key ) ) ;
2015-09-09 12:11:05 +00:00
}
2015-05-22 13:36:52 +00:00
g_key_file_set_string_list ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_FILESYSTEMS ,
2016-05-06 14:03:27 +00:00
( const char * const * ) array - > pdata , array - > len ) ;
2015-05-22 13:36:52 +00:00
}
else
2016-05-06 14:03:27 +00:00
{
g_key_file_remove_key ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_FILESYSTEMS ,
2016-05-06 14:03:27 +00:00
NULL ) ;
}
2015-05-22 13:36:52 +00:00
if ( g_hash_table_size ( context - > persistent ) > 0 )
{
2016-05-06 14:03:27 +00:00
g_autofree char * * keys = ( char * * ) g_hash_table_get_keys_as_array ( context - > persistent , NULL ) ;
2015-05-22 13:36:52 +00:00
g_key_file_set_string_list ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_PERSISTENT ,
2016-05-06 14:03:27 +00:00
( const char * const * ) keys , g_strv_length ( keys ) ) ;
2015-05-22 13:36:52 +00:00
}
else
2016-05-06 14:03:27 +00:00
{
g_key_file_remove_key ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_CONTEXT ,
FLATPAK_METADATA_KEY_PERSISTENT ,
2016-05-06 14:03:27 +00:00
NULL ) ;
}
2015-05-22 13:36:52 +00:00
2016-05-06 14:37:47 +00:00
g_key_file_remove_group ( metakey , FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY , NULL ) ;
2016-01-29 07:50:11 +00:00
g_hash_table_iter_init ( & iter , context - > session_bus_policy ) ;
2015-05-22 13:36:52 +00:00
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
2016-05-06 14:37:47 +00:00
FlatpakPolicy policy = GPOINTER_TO_INT ( value ) ;
2015-05-22 13:36:52 +00:00
if ( policy > 0 )
g_key_file_set_string ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY ,
( char * ) key , flatpak_policy_to_string ( policy ) ) ;
2015-05-22 13:36:52 +00:00
}
2016-05-06 14:37:47 +00:00
g_key_file_remove_group ( metakey , FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY , NULL ) ;
2016-01-29 07:50:11 +00:00
g_hash_table_iter_init ( & iter , context - > system_bus_policy ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
2016-05-06 14:37:47 +00:00
FlatpakPolicy policy = GPOINTER_TO_INT ( value ) ;
2016-01-29 07:50:11 +00:00
if ( policy > 0 )
g_key_file_set_string ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY ,
( char * ) key , flatpak_policy_to_string ( policy ) ) ;
2016-01-29 07:50:11 +00:00
}
2016-05-06 14:37:47 +00:00
g_key_file_remove_group ( metakey , FLATPAK_METADATA_GROUP_ENVIRONMENT , NULL ) ;
2015-05-22 13:36:52 +00:00
g_hash_table_iter_init ( & iter , context - > env_vars ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
g_key_file_set_string ( metakey ,
2016-05-06 14:37:47 +00:00
FLATPAK_METADATA_GROUP_ENVIRONMENT ,
2016-05-06 14:03:27 +00:00
( char * ) key , ( char * ) value ) ;
2015-05-22 13:36:52 +00:00
}
}
2015-05-25 19:36:36 +00:00
void
2016-05-06 14:37:47 +00:00
flatpak_context_allow_host_fs ( FlatpakContext * context )
2015-05-25 19:36:36 +00:00
{
2016-05-06 14:37:47 +00:00
flatpak_context_add_filesystem ( context , " host " ) ;
2015-05-25 19:36:36 +00:00
}
2016-05-26 10:23:48 +00:00
void
flatpak_context_to_args ( FlatpakContext * context ,
GPtrArray * args )
{
GHashTableIter iter ;
gpointer key , value ;
flatpak_context_shared_to_args ( context - > shares , context - > shares_valid , args ) ;
flatpak_context_sockets_to_args ( context - > sockets , context - > sockets_valid , args ) ;
flatpak_context_devices_to_args ( context - > devices , context - > devices_valid , args ) ;
g_hash_table_iter_init ( & iter , context - > env_vars ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_ptr_array_add ( args , g_strdup_printf ( " --env=%s=%s " , ( char * ) key , ( char * ) value ) ) ;
g_hash_table_iter_init ( & iter , context - > persistent ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
g_ptr_array_add ( args , g_strdup_printf ( " --persist=%s " , ( char * ) key ) ) ;
g_hash_table_iter_init ( & iter , context - > session_bus_policy ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
const char * name = key ;
FlatpakPolicy policy = GPOINTER_TO_INT ( value ) ;
g_ptr_array_add ( args , g_strdup_printf ( " --%s-name=%s " , flatpak_policy_to_string ( policy ) , name ) ) ;
}
g_hash_table_iter_init ( & iter , context - > system_bus_policy ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
const char * name = key ;
FlatpakPolicy policy = GPOINTER_TO_INT ( value ) ;
g_ptr_array_add ( args , g_strdup_printf ( " --system-%s-name=%s " , flatpak_policy_to_string ( policy ) , name ) ) ;
}
g_hash_table_iter_init ( & iter , context - > filesystems ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
FlatpakFilesystemMode mode = GPOINTER_TO_INT ( value ) ;
if ( mode = = FLATPAK_FILESYSTEM_MODE_READ_ONLY )
g_ptr_array_add ( args , g_strdup_printf ( " --filesystem=%s:ro " , ( char * ) key ) ) ;
else if ( mode = = FLATPAK_FILESYSTEM_MODE_READ_WRITE )
g_ptr_array_add ( args , g_strdup_printf ( " --filesystem=%s " , ( char * ) key ) ) ;
else
g_ptr_array_add ( args , g_strdup_printf ( " --nofilesystem=%s " , ( char * ) key ) ) ;
}
}
2015-02-13 09:29:41 +00:00
static char *
extract_unix_path_from_dbus_address ( const char * address )
{
const char * path , * path_end ;
if ( address = = NULL )
return NULL ;
if ( ! g_str_has_prefix ( address , " unix: " ) )
return NULL ;
path = strstr ( address , " path= " ) ;
if ( path = = NULL )
return NULL ;
path + = strlen ( " path= " ) ;
path_end = path ;
while ( * path_end ! = 0 & & * path_end ! = ' , ' )
path_end + + ;
return g_strndup ( path , path_end - path ) ;
}
2016-01-28 11:01:08 +00:00
# ifdef ENABLE_XAUTH
2016-05-06 14:03:27 +00:00
static gboolean
auth_streq ( char * str ,
char * au_str ,
int au_len )
2015-10-01 19:23:23 +00:00
{
return au_len = = strlen ( str ) & & memcmp ( str , au_str , au_len ) = = 0 ;
}
static void
write_xauth ( char * number , FILE * output )
{
Xauth * xa , local_xa ;
char * filename ;
FILE * f ;
struct utsname unames ;
if ( uname ( & unames ) )
{
g_warning ( " uname failed " ) ;
return ;
}
filename = XauFileName ( ) ;
f = fopen ( filename , " rb " ) ;
if ( f = = NULL )
return ;
while ( TRUE )
{
xa = XauReadAuth ( f ) ;
if ( xa = = NULL )
break ;
if ( xa - > family = = FamilyLocal & &
auth_streq ( unames . nodename , xa - > address , xa - > address_length ) & &
( xa - > number = = NULL | | auth_streq ( number , xa - > number , xa - > number_length ) ) )
{
local_xa = * xa ;
if ( local_xa . number )
{
local_xa . number = " 99 " ;
local_xa . number_length = 2 ;
}
2016-05-06 14:03:27 +00:00
if ( ! XauWriteAuth ( output , & local_xa ) )
2015-10-01 19:23:23 +00:00
g_warning ( " xauth write error " ) ;
}
2016-05-06 14:03:27 +00:00
XauDisposeAuth ( xa ) ;
2015-10-01 19:23:23 +00:00
}
fclose ( f ) ;
}
2016-01-28 11:01:08 +00:00
# endif /* ENABLE_XAUTH */
2015-10-01 19:23:23 +00:00
2015-05-12 12:44:08 +00:00
static void
2016-04-29 09:39:39 +00:00
add_args ( GPtrArray * argv_array , . . . )
{
va_list args ;
const gchar * arg ;
va_start ( args , argv_array ) ;
while ( ( arg = va_arg ( args , const gchar * ) ) )
g_ptr_array_add ( argv_array , g_strdup ( arg ) ) ;
va_end ( args ) ;
}
static int
create_tmp_fd ( const char * contents ,
2016-05-06 14:03:27 +00:00
gssize length ,
GError * * error )
2016-04-29 09:39:39 +00:00
{
char template [ ] = " /tmp/tmp_fd_XXXXXX " ;
int fd ;
if ( length < 0 )
length = strlen ( contents ) ;
fd = g_mkstemp ( template ) ;
if ( fd < 0 )
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Failed to create temporary file " ) ) ;
2016-04-29 09:39:39 +00:00
return - 1 ;
}
if ( unlink ( template ) ! = 0 )
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Failed to unlink temporary file " ) ) ;
2016-04-29 09:39:39 +00:00
close ( fd ) ;
return - 1 ;
}
while ( length > 0 )
{
gssize s ;
s = write ( fd , contents , length ) ;
if ( s < 0 )
{
int saved_errno = errno ;
if ( saved_errno = = EINTR )
continue ;
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( saved_errno ) ,
_ ( " Failed to write to temporary file " ) ) ;
2016-04-29 09:39:39 +00:00
close ( fd ) ;
return - 1 ;
}
g_assert ( s < = length ) ;
contents + = s ;
length - = s ;
}
lseek ( fd , 0 , SEEK_SET ) ;
return fd ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_run_add_x11_args ( GPtrArray * argv_array ,
2016-05-11 13:14:11 +00:00
GArray * fd_array ,
2016-05-10 08:53:24 +00:00
char * * * envp_p ,
gboolean allowed )
2015-02-13 09:29:41 +00:00
{
2016-07-15 00:27:11 +00:00
g_autofree char * x11_socket = NULL ;
2016-05-10 08:53:24 +00:00
const char * display ;
2015-02-13 09:29:41 +00:00
2016-05-10 08:53:24 +00:00
/* Always cover /tmp/.X11-unix, that way we never see the host one in case
* we have access to the host / tmp . If you request X access we ' ll put the right
* thing in this anyway .
*/
add_args ( argv_array ,
" --tmpfs " , " /tmp/.X11-unix " ,
NULL ) ;
if ( ! allowed )
{
* envp_p = g_environ_unsetenv ( * envp_p , " DISPLAY " ) ;
return ;
}
g_debug ( " Allowing x11 access " ) ;
display = g_getenv ( " DISPLAY " ) ;
2015-02-13 09:29:41 +00:00
if ( display & & display [ 0 ] = = ' : ' & & g_ascii_isdigit ( display [ 1 ] ) )
{
const char * display_nr = & display [ 1 ] ;
const char * display_nr_end = display_nr ;
2015-03-20 15:21:19 +00:00
g_autofree char * d = NULL ;
2015-10-01 19:23:23 +00:00
g_autofree char * tmp_path = NULL ;
2015-02-13 09:29:41 +00:00
while ( g_ascii_isdigit ( * display_nr_end ) )
display_nr_end + + ;
d = g_strndup ( display_nr , display_nr_end - display_nr ) ;
x11_socket = g_strdup_printf ( " /tmp/.X11-unix/X%s " , d ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , x11_socket , " /tmp/.X11-unix/X99 " ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " DISPLAY " , " :99.0 " , TRUE ) ;
2015-10-01 19:23:23 +00:00
2016-01-28 11:01:08 +00:00
# ifdef ENABLE_XAUTH
int fd ;
2016-05-09 09:07:53 +00:00
fd = g_file_open_tmp ( " flatpak-xauth-XXXXXX " , & tmp_path , NULL ) ;
2015-10-01 19:23:23 +00:00
if ( fd > = 0 )
{
2016-01-28 11:01:08 +00:00
FILE * output = fdopen ( fd , " wb " ) ;
2015-10-01 19:23:23 +00:00
if ( output ! = NULL )
{
2016-04-29 09:39:39 +00:00
int tmp_fd = dup ( fd ) ;
if ( tmp_fd ! = - 1 )
{
g_autofree char * tmp_fd_str = g_strdup_printf ( " %d " , tmp_fd ) ;
2016-05-06 14:03:27 +00:00
g_autofree char * dest = g_strdup_printf ( " /run/user/%d/Xauthority " , getuid ( ) ) ;
2016-04-29 09:39:39 +00:00
write_xauth ( d , output ) ;
add_args ( argv_array ,
" --bind-data " , tmp_fd_str , dest ,
NULL ) ;
2016-05-11 13:14:11 +00:00
if ( fd_array )
g_array_append_val ( fd_array , tmp_fd ) ;
2016-04-29 09:39:39 +00:00
* envp_p = g_environ_setenv ( * envp_p , " XAUTHORITY " , dest , TRUE ) ;
}
2015-10-01 19:23:23 +00:00
fclose ( output ) ;
2016-04-29 09:39:39 +00:00
unlink ( tmp_path ) ;
2015-10-01 19:23:23 +00:00
2016-04-29 09:39:39 +00:00
lseek ( tmp_fd , 0 , SEEK_SET ) ;
2015-10-01 19:23:23 +00:00
}
else
2016-05-06 14:03:27 +00:00
{
close ( fd ) ;
}
2015-10-01 19:23:23 +00:00
}
2016-01-28 11:01:08 +00:00
# endif
2015-02-13 09:29:41 +00:00
}
2016-04-29 09:39:39 +00:00
else
2016-05-06 14:03:27 +00:00
{
* envp_p = g_environ_unsetenv ( * envp_p , " DISPLAY " ) ;
}
2016-04-29 09:39:39 +00:00
2015-02-13 09:29:41 +00:00
}
2015-05-12 12:44:08 +00:00
static void
2016-05-06 14:37:47 +00:00
flatpak_run_add_wayland_args ( GPtrArray * argv_array ,
2016-05-06 14:03:27 +00:00
char * * * envp_p )
2015-02-13 09:29:41 +00:00
{
2016-04-29 09:39:39 +00:00
g_autofree char * wayland_socket = g_build_filename ( g_get_user_runtime_dir ( ) , " wayland-0 " , NULL ) ;
g_autofree char * sandbox_wayland_socket = g_strdup_printf ( " /run/user/%d/wayland-0 " , getuid ( ) ) ;
2015-02-13 09:29:41 +00:00
if ( g_file_test ( wayland_socket , G_FILE_TEST_EXISTS ) )
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , wayland_socket , sandbox_wayland_socket ,
NULL ) ;
2015-02-13 09:29:41 +00:00
}
}
2015-05-12 12:44:08 +00:00
static void
2016-05-06 14:37:47 +00:00
flatpak_run_add_pulseaudio_args ( GPtrArray * argv_array ,
2016-05-11 13:14:11 +00:00
GArray * fd_array ,
2016-05-06 14:03:27 +00:00
char * * * envp_p )
2015-02-13 09:29:41 +00:00
{
2016-07-15 00:27:11 +00:00
g_autofree char * pulseaudio_socket = g_build_filename ( g_get_user_runtime_dir ( ) , " pulse/native " , NULL ) ;
2016-04-29 09:39:39 +00:00
* envp_p = g_environ_unsetenv ( * envp_p , " PULSE_SERVER " ) ;
2015-02-13 09:29:41 +00:00
if ( g_file_test ( pulseaudio_socket , G_FILE_TEST_EXISTS ) )
{
2016-04-29 09:39:39 +00:00
gboolean share_shm = FALSE ; /* TODO: When do we add this? */
g_autofree char * client_config = g_strdup_printf ( " enable-shm=%s \n " , share_shm ? " yes " : " no " ) ;
g_autofree char * sandbox_socket_path = g_strdup_printf ( " /run/user/%d/pulse/native " , getuid ( ) ) ;
g_autofree char * pulse_server = g_strdup_printf ( " unix:/run/user/%d/pulse/native " , getuid ( ) ) ;
g_autofree char * config_path = g_strdup_printf ( " /run/user/%d/pulse/config " , getuid ( ) ) ;
int fd ;
g_autofree char * fd_str = NULL ;
fd = create_tmp_fd ( client_config , - 1 , NULL ) ;
if ( fd = = - 1 )
return ;
fd_str = g_strdup_printf ( " %d " , fd ) ;
2016-05-11 13:14:11 +00:00
if ( fd_array )
g_array_append_val ( fd_array , fd ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , pulseaudio_socket , sandbox_socket_path ,
" --bind-data " , fd_str , config_path ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " PULSE_SERVER " , pulse_server , TRUE ) ;
* envp_p = g_environ_setenv ( * envp_p , " PULSE_CLIENTCONFIG " , config_path , TRUE ) ;
2015-02-13 09:29:41 +00:00
}
}
2016-06-24 05:52:55 +00:00
static void
2016-06-28 13:05:01 +00:00
flatpak_run_add_journal_args ( GPtrArray * argv_array )
2016-06-24 05:52:55 +00:00
{
2016-07-15 00:27:11 +00:00
g_autofree char * journal_socket_socket = g_strdup ( " /run/systemd/journal/socket " ) ;
g_autofree char * journal_stdout_socket = g_strdup ( " /run/systemd/journal/stdout " ) ;
2016-06-24 05:52:55 +00:00
if ( g_file_test ( journal_socket_socket , G_FILE_TEST_EXISTS ) )
{
add_args ( argv_array ,
" --bind " , journal_socket_socket , journal_socket_socket ,
NULL ) ;
}
if ( g_file_test ( journal_stdout_socket , G_FILE_TEST_EXISTS ) )
{
add_args ( argv_array ,
" --bind " , journal_stdout_socket , journal_stdout_socket ,
NULL ) ;
}
}
2015-05-07 17:17:03 +00:00
static char *
create_proxy_socket ( char * template )
{
2016-06-16 20:29:16 +00:00
g_autofree char * proxy_socket = g_build_filename ( g_get_user_runtime_dir ( ) , template , NULL ) ;
2015-05-07 17:17:03 +00:00
int fd ;
fd = g_mkstemp ( proxy_socket ) ;
if ( fd = = - 1 )
return NULL ;
close ( fd ) ;
return g_steal_pointer ( & proxy_socket ) ;
}
2016-01-29 07:50:11 +00:00
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_add_system_dbus_args ( FlatpakContext * context ,
char * * * envp_p ,
GPtrArray * argv_array ,
GPtrArray * dbus_proxy_argv ,
gboolean unrestricted )
2015-02-13 09:29:41 +00:00
{
const char * dbus_address = g_getenv ( " DBUS_SYSTEM_BUS_ADDRESS " ) ;
2016-01-29 07:50:11 +00:00
g_autofree char * real_dbus_address = NULL ;
2016-06-10 10:59:30 +00:00
g_autofree char * dbus_system_socket = NULL ;
2015-02-13 09:29:41 +00:00
2015-05-07 17:17:03 +00:00
if ( dbus_address ! = NULL )
dbus_system_socket = extract_unix_path_from_dbus_address ( dbus_address ) ;
else if ( g_file_test ( " /var/run/dbus/system_bus_socket " , G_FILE_TEST_EXISTS ) )
dbus_system_socket = g_strdup ( " /var/run/dbus/system_bus_socket " ) ;
2015-02-13 09:29:41 +00:00
2016-01-29 07:50:11 +00:00
if ( dbus_system_socket ! = NULL & & unrestricted )
2015-02-13 09:29:41 +00:00
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , dbus_system_socket , " /run/dbus/system_bus_socket " ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " DBUS_SYSTEM_BUS_ADDRESS " , " unix:path=/run/dbus/system_bus_socket " , TRUE ) ;
2016-01-29 07:50:11 +00:00
return TRUE ;
2015-02-13 09:29:41 +00:00
}
2016-01-29 07:50:11 +00:00
else if ( dbus_proxy_argv & &
g_hash_table_size ( context - > system_bus_policy ) > 0 )
2015-05-07 17:17:03 +00:00
{
2016-06-16 20:29:16 +00:00
g_autofree char * proxy_socket = create_proxy_socket ( " .system-bus-proxy-XXXXXX " ) ;
2015-05-07 17:17:03 +00:00
if ( proxy_socket = = NULL )
2016-04-29 09:39:39 +00:00
return FALSE ;
2015-05-07 17:17:03 +00:00
2016-01-29 07:50:11 +00:00
if ( dbus_address )
real_dbus_address = g_strdup ( dbus_address ) ;
else
real_dbus_address = g_strdup_printf ( " unix:path=%s " , dbus_system_socket ) ;
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( real_dbus_address ) ) ;
2015-05-07 17:17:03 +00:00
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( proxy_socket ) ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , proxy_socket , " /run/dbus/system_bus_socket " ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " DBUS_SYSTEM_BUS_ADDRESS " , " unix:path=/run/dbus/system_bus_socket " , TRUE ) ;
2016-01-29 07:50:11 +00:00
return TRUE ;
2015-05-07 17:17:03 +00:00
}
2016-01-29 07:50:11 +00:00
return FALSE ;
2015-02-13 09:29:41 +00:00
}
2015-05-12 12:44:08 +00:00
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_add_session_dbus_args ( GPtrArray * argv_array ,
2016-05-06 14:03:27 +00:00
char * * * envp_p ,
2015-05-12 12:44:08 +00:00
GPtrArray * dbus_proxy_argv ,
2016-05-06 14:03:27 +00:00
gboolean unrestricted )
2015-02-13 09:29:41 +00:00
{
const char * dbus_address = g_getenv ( " DBUS_SESSION_BUS_ADDRESS " ) ;
char * dbus_session_socket = NULL ;
2016-04-29 09:39:39 +00:00
g_autofree char * sandbox_socket_path = g_strdup_printf ( " /run/user/%d/bus " , getuid ( ) ) ;
g_autofree char * sandbox_dbus_address = g_strdup_printf ( " unix:path=/run/user/%d/bus " , getuid ( ) ) ;
2015-02-13 09:29:41 +00:00
2015-05-07 17:17:03 +00:00
if ( dbus_address = = NULL )
2015-05-12 12:44:08 +00:00
return FALSE ;
2015-05-07 17:17:03 +00:00
2015-02-13 09:29:41 +00:00
dbus_session_socket = extract_unix_path_from_dbus_address ( dbus_address ) ;
2015-05-12 12:44:08 +00:00
if ( dbus_session_socket ! = NULL & & unrestricted )
2015-02-13 09:29:41 +00:00
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , dbus_session_socket , sandbox_socket_path ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " DBUS_SESSION_BUS_ADDRESS " , sandbox_dbus_address , TRUE ) ;
2015-05-12 12:44:08 +00:00
return TRUE ;
2015-02-13 09:29:41 +00:00
}
2015-05-07 17:17:03 +00:00
else if ( dbus_proxy_argv & & dbus_address ! = NULL )
{
2016-06-16 20:29:16 +00:00
g_autofree char * proxy_socket = create_proxy_socket ( " .session-bus-proxy-XXXXXX " ) ;
2015-05-07 17:17:03 +00:00
if ( proxy_socket = = NULL )
2016-04-29 09:39:39 +00:00
return FALSE ;
2015-05-07 17:17:03 +00:00
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( dbus_address ) ) ;
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( proxy_socket ) ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , proxy_socket , sandbox_socket_path ,
NULL ) ;
* envp_p = g_environ_setenv ( * envp_p , " DBUS_SESSION_BUS_ADDRESS " , sandbox_dbus_address , TRUE ) ;
2015-05-12 12:44:08 +00:00
return TRUE ;
2015-05-07 17:17:03 +00:00
}
2015-05-12 12:44:08 +00:00
return FALSE ;
}
static void
2016-05-06 14:37:47 +00:00
flatpak_add_bus_filters ( GPtrArray * dbus_proxy_argv ,
GHashTable * ht ,
const char * app_id ,
FlatpakContext * context )
2015-05-12 12:44:08 +00:00
{
2015-05-22 14:55:45 +00:00
GHashTableIter iter ;
gpointer key , value ;
2015-05-12 12:44:08 +00:00
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( " --filter " ) ) ;
2016-01-29 07:50:11 +00:00
if ( app_id )
{
g_ptr_array_add ( dbus_proxy_argv , g_strdup_printf ( " --own=%s " , app_id ) ) ;
g_ptr_array_add ( dbus_proxy_argv , g_strdup_printf ( " --own=%s.* " , app_id ) ) ;
}
2015-05-12 12:44:08 +00:00
2016-01-29 07:50:11 +00:00
g_hash_table_iter_init ( & iter , ht ) ;
2015-05-22 14:55:45 +00:00
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
{
2016-05-06 14:37:47 +00:00
FlatpakPolicy policy = GPOINTER_TO_INT ( value ) ;
2015-05-22 14:55:45 +00:00
if ( policy > 0 )
2016-05-06 14:37:47 +00:00
g_ptr_array_add ( dbus_proxy_argv , g_strdup_printf ( " --%s=%s " , flatpak_policy_to_string ( policy ) , ( char * ) key ) ) ;
2015-05-22 14:55:45 +00:00
}
2015-02-13 09:29:41 +00:00
}
2015-02-13 09:41:01 +00:00
2015-09-22 11:57:20 +00:00
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_add_extension_args ( GPtrArray * argv_array ,
2016-05-06 14:03:27 +00:00
GKeyFile * metakey ,
const char * full_ref ,
2015-09-22 11:57:20 +00:00
GCancellable * cancellable ,
2016-05-06 14:03:27 +00:00
GError * * error )
2015-09-22 11:57:20 +00:00
{
g_auto ( GStrv ) parts = NULL ;
2016-01-11 14:34:54 +00:00
gboolean is_app ;
2016-01-20 11:33:55 +00:00
GList * extensions , * l ;
2015-09-22 11:57:20 +00:00
parts = g_strsplit ( full_ref , " / " , 0 ) ;
if ( g_strv_length ( parts ) ! = 4 )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Failed to determine parts from ref: %s " , full_ref ) ;
2015-09-22 11:57:20 +00:00
2016-01-11 14:34:54 +00:00
is_app = strcmp ( parts [ 0 ] , " app " ) = = 0 ;
2016-05-06 14:37:47 +00:00
extensions = flatpak_list_extensions ( metakey ,
2016-01-20 11:33:55 +00:00
parts [ 2 ] , parts [ 3 ] ) ;
for ( l = extensions ; l ! = NULL ; l = l - > next )
2015-09-22 11:57:20 +00:00
{
2016-05-06 14:37:47 +00:00
FlatpakExtension * ext = l - > data ;
2016-06-29 08:24:50 +00:00
g_autofree char * full_directory = g_build_filename ( is_app ? " /app " : " /usr " , ext - > directory , NULL ) ;
g_autofree char * ref = g_build_filename ( full_directory , " .ref " , NULL ) ;
g_autofree char * real_ref = g_build_filename ( ext - > files_path , ext - > directory , " .ref " , NULL ) ;
2015-09-22 11:57:20 +00:00
2016-06-29 13:56:10 +00:00
if ( ext - > needs_tmpfs )
{
g_autofree char * parent = g_path_get_dirname ( full_directory ) ;
add_args ( argv_array ,
" --tmpfs " , parent ,
NULL ) ;
}
2016-06-29 08:24:50 +00:00
add_args ( argv_array ,
" --bind " , ext - > files_path , full_directory ,
NULL ) ;
if ( g_file_test ( real_ref , G_FILE_TEST_EXISTS ) )
add_args ( argv_array ,
" --lock-file " , ref ,
NULL ) ;
2015-09-22 11:57:20 +00:00
}
2016-05-06 14:37:47 +00:00
g_list_free_full ( extensions , ( GDestroyNotify ) flatpak_extension_free ) ;
2016-01-20 11:33:55 +00:00
2015-09-22 11:57:20 +00:00
return TRUE ;
}
2016-04-29 09:39:39 +00:00
static void
2016-05-06 14:37:47 +00:00
add_file_arg ( GPtrArray * argv_array ,
FlatpakFilesystemMode mode ,
const char * path )
2016-04-29 09:39:39 +00:00
{
struct stat st ;
if ( stat ( path , & st ) ! = 0 )
return ;
if ( S_ISDIR ( st . st_mode ) | |
S_ISREG ( st . st_mode ) )
{
add_args ( argv_array ,
2016-05-06 14:37:47 +00:00
( mode = = FLATPAK_FILESYSTEM_MODE_READ_WRITE ) ? " --bind " : " --ro-bind " ,
2016-04-29 09:39:39 +00:00
path , path , NULL ) ;
}
}
2015-02-13 09:41:01 +00:00
void
2016-05-06 14:37:47 +00:00
flatpak_run_add_environment_args ( GPtrArray * argv_array ,
2016-05-11 13:14:11 +00:00
GArray * fd_array ,
2016-05-06 14:37:47 +00:00
char * * * envp_p ,
GPtrArray * session_bus_proxy_argv ,
GPtrArray * system_bus_proxy_argv ,
const char * app_id ,
FlatpakContext * context ,
GFile * app_id_dir )
2015-02-13 09:41:01 +00:00
{
2015-05-25 13:28:29 +00:00
GHashTableIter iter ;
2015-09-09 12:11:05 +00:00
gpointer key , value ;
2015-05-12 12:44:08 +00:00
gboolean unrestricted_session_bus ;
2016-01-29 07:50:11 +00:00
gboolean unrestricted_system_bus ;
2015-05-25 13:28:29 +00:00
gboolean home_access = FALSE ;
GString * xdg_dirs_conf = NULL ;
2016-05-06 14:37:47 +00:00
FlatpakFilesystemMode fs_mode , home_mode ;
2015-02-19 19:57:53 +00:00
2016-05-06 14:37:47 +00:00
if ( ( context - > shares & FLATPAK_CONTEXT_SHARED_IPC ) = = 0 )
2015-02-13 09:41:01 +00:00
{
2016-04-29 09:39:39 +00:00
g_debug ( " Disallowing ipc access " ) ;
add_args ( argv_array , " --unshare-ipc " , NULL ) ;
2015-02-13 09:41:01 +00:00
}
2016-05-06 14:37:47 +00:00
if ( ( context - > shares & FLATPAK_CONTEXT_SHARED_NETWORK ) = = 0 )
2015-05-22 14:55:45 +00:00
{
2016-04-29 09:39:39 +00:00
g_debug ( " Disallowing network access " ) ;
add_args ( argv_array , " --unshare-net " , NULL ) ;
2015-05-22 14:55:45 +00:00
}
2016-06-14 20:33:14 +00:00
if ( context - > devices & FLATPAK_CONTEXT_DEVICE_ALL )
2015-03-05 14:55:36 +00:00
{
2016-06-14 20:33:14 +00:00
add_args ( argv_array ,
2016-06-18 20:52:39 +00:00
" --dev-bind " , " /dev " , " /dev " ,
2016-06-14 20:33:14 +00:00
NULL ) ;
}
else
{
add_args ( argv_array ,
" --dev " , " /dev " ,
NULL ) ;
if ( context - > devices & FLATPAK_CONTEXT_DEVICE_DRI )
2016-05-06 14:03:27 +00:00
{
2016-06-14 20:33:14 +00:00
g_debug ( " Allowing dri access " ) ;
if ( g_file_test ( " /dev/dri " , G_FILE_TEST_IS_DIR ) )
add_args ( argv_array , " --dev-bind " , " /dev/dri " , " /dev/dri " , NULL ) ;
if ( g_file_test ( " /dev/nvidiactl " , G_FILE_TEST_EXISTS ) )
{
add_args ( argv_array ,
" --dev-bind " , " /dev/nvidiactl " , " /dev/nvidiactl " ,
" --dev-bind " , " /dev/nvidia0 " , " /dev/nvidia0 " ,
NULL ) ;
}
2016-05-06 14:03:27 +00:00
}
2015-03-05 14:55:36 +00:00
}
2016-05-06 14:37:47 +00:00
fs_mode = ( FlatpakFilesystemMode ) g_hash_table_lookup ( context - > filesystems , " host " ) ;
2015-11-26 16:22:37 +00:00
if ( fs_mode ! = 0 )
2015-02-13 09:41:01 +00:00
{
2016-04-29 09:39:39 +00:00
DIR * dir ;
struct dirent * dirent ;
2015-02-13 09:41:01 +00:00
g_debug ( " Allowing host-fs access " ) ;
2015-05-25 13:28:29 +00:00
home_access = TRUE ;
2016-04-29 09:39:39 +00:00
/* Bind mount most dirs in / into the new root */
dir = opendir ( " / " ) ;
if ( dir ! = NULL )
{
while ( ( dirent = readdir ( dir ) ) )
{
g_autofree char * path = NULL ;
if ( g_strv_contains ( dont_mount_in_root , dirent - > d_name ) )
continue ;
path = g_build_filename ( " / " , dirent - > d_name , NULL ) ;
add_file_arg ( argv_array , fs_mode , path ) ;
}
2016-06-10 10:59:30 +00:00
closedir ( dir ) ;
2016-04-29 09:39:39 +00:00
}
add_file_arg ( argv_array , fs_mode , " /run/media " ) ;
2015-02-13 09:41:01 +00:00
}
2015-11-26 16:22:37 +00:00
2016-05-06 14:37:47 +00:00
home_mode = ( FlatpakFilesystemMode ) g_hash_table_lookup ( context - > filesystems , " home " ) ;
2015-11-26 16:22:37 +00:00
if ( home_mode ! = 0 )
2015-02-13 09:41:01 +00:00
{
g_debug ( " Allowing homedir access " ) ;
2015-05-25 13:28:29 +00:00
home_access = TRUE ;
2016-04-29 09:39:39 +00:00
add_file_arg ( argv_array , MAX ( home_mode , fs_mode ) , g_get_home_dir ( ) ) ;
2015-02-13 09:41:01 +00:00
}
2015-11-26 16:22:37 +00:00
if ( ! home_access )
2015-05-25 09:30:53 +00:00
{
2016-05-17 07:28:33 +00:00
/* Enable persistent mapping only if no access to real home dir */
2015-05-25 09:30:53 +00:00
g_hash_table_iter_init ( & iter , context - > persistent ) ;
while ( g_hash_table_iter_next ( & iter , & key , NULL ) )
{
const char * persist = key ;
g_autofree char * src = g_build_filename ( g_get_home_dir ( ) , " .var/app " , app_id , persist , NULL ) ;
g_autofree char * dest = g_build_filename ( g_get_home_dir ( ) , persist , NULL ) ;
g_mkdir_with_parents ( src , 0755 ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , src , dest ,
NULL ) ;
2015-05-25 09:30:53 +00:00
}
2015-05-25 13:28:29 +00:00
}
2016-08-24 12:11:45 +00:00
{
g_autofree char * run_user_app_dst = g_strdup_printf ( " /run/user/%d/app/%s " , getuid ( ) , app_id ) ;
g_autofree char * run_user_app_src = g_build_filename ( g_get_user_runtime_dir ( ) , " app " , app_id , NULL ) ;
if ( glnx_shutil_mkdir_p_at ( AT_FDCWD ,
run_user_app_src ,
0700 ,
NULL ,
NULL ) )
add_args ( argv_array ,
" --bind " , run_user_app_src , run_user_app_dst ,
NULL ) ;
}
2015-05-25 13:28:29 +00:00
g_hash_table_iter_init ( & iter , context - > filesystems ) ;
2015-09-09 12:11:05 +00:00
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
2015-05-25 13:28:29 +00:00
{
const char * filesystem = key ;
2016-05-06 14:37:47 +00:00
FlatpakFilesystemMode mode = GPOINTER_TO_INT ( value ) ;
2015-05-25 13:28:29 +00:00
2015-09-09 12:11:05 +00:00
if ( value = = NULL | |
strcmp ( filesystem , " host " ) = = 0 | |
2015-05-25 13:28:29 +00:00
strcmp ( filesystem , " home " ) = = 0 )
continue ;
if ( g_str_has_prefix ( filesystem , " xdg- " ) )
{
2016-02-25 15:51:45 +00:00
const char * path , * rest = NULL ;
2016-02-25 16:11:37 +00:00
const char * config_key = NULL ;
2016-02-25 15:51:45 +00:00
g_autofree char * subpath = NULL ;
2015-05-25 13:28:29 +00:00
2016-04-20 12:26:03 +00:00
if ( ! get_user_dir_from_string ( filesystem , & config_key , & rest , & path ) )
2015-05-25 13:28:29 +00:00
{
g_warning ( " Unsupported xdg dir %s \n " , filesystem ) ;
continue ;
}
2016-05-25 12:12:09 +00:00
if ( path = = NULL )
continue ; /* Unconfigured, ignore */
2015-05-25 13:28:29 +00:00
if ( strcmp ( path , g_get_home_dir ( ) ) = = 0 )
{
/* xdg-user-dirs sets disabled dirs to $HOME, and its in general not a good
idea to set full access to $ HOME other than explicitly , so we ignore
these */
g_debug ( " Xdg dir %s is $HOME (i.e. disabled), ignoring \n " , filesystem ) ;
continue ;
}
2016-02-25 15:51:45 +00:00
subpath = g_build_filename ( path , rest , NULL ) ;
if ( g_file_test ( subpath , G_FILE_TEST_EXISTS ) )
2015-05-25 13:28:29 +00:00
{
if ( xdg_dirs_conf = = NULL )
xdg_dirs_conf = g_string_new ( " " ) ;
2016-02-25 16:11:37 +00:00
if ( config_key )
g_string_append_printf ( xdg_dirs_conf , " %s= \" %s \" \n " ,
config_key , path ) ;
2015-05-25 13:28:29 +00:00
2016-04-29 09:39:39 +00:00
add_file_arg ( argv_array , mode , subpath ) ;
2015-05-25 13:28:29 +00:00
}
}
else if ( g_str_has_prefix ( filesystem , " ~/ " ) )
{
g_autofree char * path = NULL ;
2016-05-06 14:03:27 +00:00
path = g_build_filename ( g_get_home_dir ( ) , filesystem + 2 , NULL ) ;
2015-11-26 14:37:17 +00:00
if ( g_file_test ( path , G_FILE_TEST_EXISTS ) )
2016-04-29 09:39:39 +00:00
add_file_arg ( argv_array , mode , path ) ;
2015-05-25 13:28:29 +00:00
}
else if ( g_str_has_prefix ( filesystem , " / " ) )
{
if ( g_file_test ( filesystem , G_FILE_TEST_EXISTS ) )
2016-04-29 09:39:39 +00:00
add_file_arg ( argv_array , mode , filesystem ) ;
2015-05-25 13:28:29 +00:00
}
else
2016-05-06 14:03:27 +00:00
{
g_warning ( " Unexpected filesystem arg %s \n " , filesystem ) ;
}
2015-05-25 13:28:29 +00:00
}
2016-04-29 09:39:39 +00:00
/* Do this after setting up everything in the home dir, so its not overwritten */
if ( app_id_dir )
add_args ( argv_array ,
2016-08-22 08:20:19 +00:00
" --bind " , flatpak_file_get_path_cached ( app_id_dir ) , flatpak_file_get_path_cached ( app_id_dir ) ,
2016-04-29 09:39:39 +00:00
NULL ) ;
2015-07-10 10:36:54 +00:00
if ( home_access & & app_id_dir ! = NULL )
{
g_autofree char * src_path = g_build_filename ( g_get_user_config_dir ( ) ,
" user-dirs.dirs " ,
NULL ) ;
2016-08-22 08:20:19 +00:00
g_autofree char * path = g_build_filename ( flatpak_file_get_path_cached ( app_id_dir ) ,
2015-07-10 10:36:54 +00:00
" config/user-dirs.dirs " , NULL ) ;
2016-05-12 06:45:40 +00:00
if ( g_file_test ( src_path , G_FILE_TEST_EXISTS ) )
add_args ( argv_array ,
" --ro-bind " , src_path , path ,
NULL ) ;
2015-07-10 10:36:54 +00:00
}
else if ( xdg_dirs_conf ! = NULL & & app_id_dir ! = NULL )
2015-05-25 13:28:29 +00:00
{
g_autofree char * tmp_path = NULL ;
g_autofree char * path = NULL ;
int fd ;
2016-05-09 09:07:53 +00:00
fd = g_file_open_tmp ( " flatpak-user-dir-XXXXXX.dirs " , & tmp_path , NULL ) ;
2015-05-25 13:28:29 +00:00
if ( fd > = 0 )
{
close ( fd ) ;
if ( g_file_set_contents ( tmp_path , xdg_dirs_conf - > str , xdg_dirs_conf - > len , NULL ) )
{
2016-04-29 09:39:39 +00:00
int tmp_fd = open ( tmp_path , O_RDONLY ) ;
unlink ( tmp_path ) ;
2016-05-11 13:14:11 +00:00
if ( tmp_fd ! = - 1 )
2016-04-29 09:39:39 +00:00
{
g_autofree char * tmp_fd_str = g_strdup_printf ( " %d " , tmp_fd ) ;
2016-05-11 13:14:11 +00:00
if ( fd_array )
g_array_append_val ( fd_array , tmp_fd ) ;
2016-08-22 08:20:19 +00:00
path = g_build_filename ( flatpak_file_get_path_cached ( app_id_dir ) ,
2016-04-29 09:39:39 +00:00
" config/user-dirs.dirs " , NULL ) ;
add_args ( argv_array , " --file " , tmp_fd_str , path , NULL ) ;
}
2015-05-25 13:28:29 +00:00
}
}
g_string_free ( xdg_dirs_conf , TRUE ) ;
2015-05-25 09:30:53 +00:00
}
2015-02-13 09:41:01 +00:00
2016-05-11 13:14:11 +00:00
flatpak_run_add_x11_args ( argv_array , fd_array , envp_p ,
2016-05-10 08:53:24 +00:00
( context - > sockets & FLATPAK_CONTEXT_SOCKET_X11 ) ! = 0 ) ;
2015-02-13 09:41:01 +00:00
2016-05-06 14:37:47 +00:00
if ( context - > sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND )
2015-02-13 09:41:01 +00:00
{
g_debug ( " Allowing wayland access " ) ;
2016-05-06 14:37:47 +00:00
flatpak_run_add_wayland_args ( argv_array , envp_p ) ;
2015-02-13 09:41:01 +00:00
}
2016-05-06 14:37:47 +00:00
if ( context - > sockets & FLATPAK_CONTEXT_SOCKET_PULSEAUDIO )
2015-02-13 09:41:01 +00:00
{
g_debug ( " Allowing pulseaudio access " ) ;
2016-05-11 13:14:11 +00:00
flatpak_run_add_pulseaudio_args ( argv_array , fd_array , envp_p ) ;
2015-02-13 09:41:01 +00:00
}
2016-05-06 14:37:47 +00:00
unrestricted_session_bus = ( context - > sockets & FLATPAK_CONTEXT_SOCKET_SESSION_BUS ) ! = 0 ;
2015-05-22 14:55:45 +00:00
if ( unrestricted_session_bus )
g_debug ( " Allowing session-dbus access " ) ;
2016-05-06 14:37:47 +00:00
if ( flatpak_run_add_session_dbus_args ( argv_array , envp_p , session_bus_proxy_argv , unrestricted_session_bus ) & &
2016-01-29 07:50:11 +00:00
! unrestricted_session_bus & & session_bus_proxy_argv )
2016-05-06 14:37:47 +00:00
flatpak_add_bus_filters ( session_bus_proxy_argv , context - > session_bus_policy , app_id , context ) ;
2015-05-12 12:44:08 +00:00
2016-05-06 14:37:47 +00:00
unrestricted_system_bus = ( context - > sockets & FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS ) ! = 0 ;
2016-01-29 07:50:11 +00:00
if ( unrestricted_system_bus )
g_debug ( " Allowing system-dbus access " ) ;
2016-05-06 14:37:47 +00:00
if ( flatpak_run_add_system_dbus_args ( context , envp_p , argv_array , system_bus_proxy_argv ,
2016-01-29 07:50:11 +00:00
unrestricted_system_bus ) & &
! unrestricted_system_bus & & system_bus_proxy_argv )
2016-05-06 14:37:47 +00:00
flatpak_add_bus_filters ( system_bus_proxy_argv , context - > system_bus_policy , NULL , context ) ;
2015-02-19 19:57:53 +00:00
2016-05-26 07:43:56 +00:00
if ( g_environ_getenv ( * envp_p , " LD_LIBRARY_PATH " ) ! = NULL )
{
/* LD_LIBRARY_PATH is overridden for setuid helper, so pass it as cmdline arg */
add_args ( argv_array ,
" --setenv " , " LD_LIBRARY_PATH " , g_environ_getenv ( * envp_p , " LD_LIBRARY_PATH " ) ,
NULL ) ;
* envp_p = g_environ_unsetenv ( * envp_p , " LD_LIBRARY_PATH " ) ;
}
2015-02-13 09:41:01 +00:00
}
2015-02-19 18:52:17 +00:00
2016-05-06 14:03:27 +00:00
static const struct { const char * env ;
const char * val ;
} default_exports [ ] = {
{ " PATH " , " /app/bin:/usr/bin " } ,
2016-04-29 09:39:39 +00:00
{ " LD_LIBRARY_PATH " , " /app/lib " } ,
2016-05-06 14:03:27 +00:00
{ " XDG_CONFIG_DIRS " , " /app/etc/xdg:/etc/xdg " } ,
{ " XDG_DATA_DIRS " , " /app/share:/usr/share " } ,
{ " SHELL " , " /bin/sh " } ,
2015-05-12 09:37:50 +00:00
} ;
2016-05-06 14:03:27 +00:00
static const struct { const char * env ;
const char * val ;
} devel_exports [ ] = {
{ " ACLOCAL_PATH " , " /app/share/aclocal " } ,
{ " C_INCLUDE_PATH " , " /app/include " } ,
{ " CPLUS_INCLUDE_PATH " , " /app/include " } ,
{ " LDFLAGS " , " -L/app/lib " } ,
{ " PKG_CONFIG_PATH " , " /app/lib/pkgconfig:/app/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig " } ,
{ " LC_ALL " , " en_US.utf8 " } ,
2015-05-12 09:37:50 +00:00
} ;
2015-05-12 09:05:52 +00:00
char * *
2016-05-06 14:37:47 +00:00
flatpak_run_get_minimal_env ( gboolean devel )
2015-02-19 18:52:17 +00:00
{
2015-05-12 09:05:52 +00:00
GPtrArray * env_array ;
2015-08-27 14:16:58 +00:00
static const char * const copy [ ] = {
2015-11-25 12:16:33 +00:00
" PWD " ,
2015-02-19 18:52:17 +00:00
" GDMSESSION " ,
" XDG_CURRENT_DESKTOP " ,
" XDG_SESSION_DESKTOP " ,
" DESKTOP_SESSION " ,
" EMAIL_ADDRESS " ,
" HOME " ,
" HOSTNAME " ,
" LOGNAME " ,
" REAL_NAME " ,
" TERM " ,
" USER " ,
" USERNAME " ,
} ;
2015-08-27 14:16:58 +00:00
static const char * const copy_nodevel [ ] = {
2015-02-19 18:52:17 +00:00
" LANG " ,
" LANGUAGE " ,
" LC_ALL " ,
" LC_ADDRESS " ,
" LC_COLLATE " ,
" LC_CTYPE " ,
" LC_IDENTIFICATION " ,
" LC_MEASUREMENT " ,
" LC_MESSAGES " ,
" LC_MONETARY " ,
" LC_NAME " ,
" LC_NUMERIC " ,
" LC_PAPER " ,
" LC_TELEPHONE " ,
" LC_TIME " ,
} ;
int i ;
2015-05-12 09:05:52 +00:00
env_array = g_ptr_array_new_with_free_func ( g_free ) ;
2016-05-06 14:03:27 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( default_exports ) ; i + + )
2015-05-12 09:37:50 +00:00
g_ptr_array_add ( env_array , g_strdup_printf ( " %s=%s " , default_exports [ i ] . env , default_exports [ i ] . val ) ) ;
2015-02-19 18:52:17 +00:00
if ( devel )
{
2015-05-12 09:37:50 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( devel_exports ) ; i + + )
g_ptr_array_add ( env_array , g_strdup_printf ( " %s=%s " , devel_exports [ i ] . env , devel_exports [ i ] . val ) ) ;
2015-02-19 18:52:17 +00:00
}
2016-05-06 14:03:27 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( copy ) ; i + + )
2015-02-19 18:52:17 +00:00
{
2016-05-06 14:03:27 +00:00
const char * current = g_getenv ( copy [ i ] ) ;
2015-02-19 18:52:17 +00:00
if ( current )
2015-05-12 09:05:52 +00:00
g_ptr_array_add ( env_array , g_strdup_printf ( " %s=%s " , copy [ i ] , current ) ) ;
2015-02-19 18:52:17 +00:00
}
if ( ! devel )
{
2016-05-06 14:03:27 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( copy_nodevel ) ; i + + )
2015-05-12 09:05:52 +00:00
{
2016-05-06 14:03:27 +00:00
const char * current = g_getenv ( copy_nodevel [ i ] ) ;
2015-05-12 09:05:52 +00:00
if ( current )
g_ptr_array_add ( env_array , g_strdup_printf ( " %s=%s " , copy_nodevel [ i ] , current ) ) ;
}
2015-02-19 18:52:17 +00:00
}
2015-05-12 09:05:52 +00:00
g_ptr_array_add ( env_array , NULL ) ;
2016-05-06 14:03:27 +00:00
return ( char * * ) g_ptr_array_free ( env_array , FALSE ) ;
2015-02-19 18:52:17 +00:00
}
2015-02-19 21:52:01 +00:00
2015-05-12 09:37:50 +00:00
char * *
2016-05-06 14:37:47 +00:00
flatpak_run_apply_env_default ( char * * envp )
2015-05-12 09:37:50 +00:00
{
int i ;
2016-05-06 14:03:27 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( default_exports ) ; i + + )
2015-05-12 09:37:50 +00:00
envp = g_environ_setenv ( envp , default_exports [ i ] . env , default_exports [ i ] . val , TRUE ) ;
return envp ;
}
char * *
2016-05-06 14:37:47 +00:00
flatpak_run_apply_env_appid ( char * * envp ,
2016-05-06 14:03:27 +00:00
GFile * app_dir )
2015-05-12 09:37:50 +00:00
{
g_autoptr ( GFile ) app_dir_data = NULL ;
g_autoptr ( GFile ) app_dir_config = NULL ;
g_autoptr ( GFile ) app_dir_cache = NULL ;
app_dir_data = g_file_get_child ( app_dir , " data " ) ;
app_dir_config = g_file_get_child ( app_dir , " config " ) ;
app_dir_cache = g_file_get_child ( app_dir , " cache " ) ;
2016-08-22 08:20:19 +00:00
envp = g_environ_setenv ( envp , " XDG_DATA_HOME " , flatpak_file_get_path_cached ( app_dir_data ) , TRUE ) ;
envp = g_environ_setenv ( envp , " XDG_CONFIG_HOME " , flatpak_file_get_path_cached ( app_dir_config ) , TRUE ) ;
envp = g_environ_setenv ( envp , " XDG_CACHE_HOME " , flatpak_file_get_path_cached ( app_dir_cache ) , TRUE ) ;
2015-05-12 09:37:50 +00:00
return envp ;
}
2015-05-12 09:13:44 +00:00
char * *
2016-05-06 14:37:47 +00:00
flatpak_run_apply_env_vars ( char * * envp , FlatpakContext * context )
2015-05-12 09:13:44 +00:00
{
2015-05-22 14:55:45 +00:00
GHashTableIter iter ;
gpointer key , value ;
2015-05-12 09:13:44 +00:00
2015-05-22 14:55:45 +00:00
g_hash_table_iter_init ( & iter , context - > env_vars ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) )
2015-05-12 09:13:44 +00:00
{
2015-05-22 14:55:45 +00:00
const char * var = key ;
const char * val = value ;
if ( val & & val [ 0 ] ! = 0 )
envp = g_environ_setenv ( envp , var , val , TRUE ) ;
else
envp = g_environ_unsetenv ( envp , var ) ;
2015-05-12 09:13:44 +00:00
}
return envp ;
}
2015-02-19 21:52:01 +00:00
GFile *
2016-05-06 14:37:47 +00:00
flatpak_get_data_dir ( const char * app_id )
2015-02-19 21:52:01 +00:00
{
2015-03-20 15:21:19 +00:00
g_autoptr ( GFile ) home = g_file_new_for_path ( g_get_home_dir ( ) ) ;
g_autoptr ( GFile ) var_app = g_file_resolve_relative_path ( home , " .var/app " ) ;
2015-02-19 21:52:01 +00:00
return g_file_get_child ( var_app , app_id ) ;
}
GFile *
2016-05-06 14:37:47 +00:00
flatpak_ensure_data_dir ( const char * app_id ,
2016-05-06 14:03:27 +00:00
GCancellable * cancellable ,
GError * * error )
2015-02-19 21:52:01 +00:00
{
2016-05-06 14:37:47 +00:00
g_autoptr ( GFile ) dir = flatpak_get_data_dir ( app_id ) ;
2015-03-20 15:21:19 +00:00
g_autoptr ( GFile ) data_dir = g_file_get_child ( dir , " data " ) ;
g_autoptr ( GFile ) cache_dir = g_file_get_child ( dir , " cache " ) ;
g_autoptr ( GFile ) config_dir = g_file_get_child ( dir , " config " ) ;
2015-02-19 21:52:01 +00:00
2016-08-22 07:15:46 +00:00
if ( ! flatpak_mkdir_p ( data_dir , cancellable , error ) )
2015-02-19 21:52:01 +00:00
return NULL ;
2016-08-22 07:15:46 +00:00
if ( ! flatpak_mkdir_p ( cache_dir , cancellable , error ) )
2015-02-19 21:52:01 +00:00
return NULL ;
2016-08-22 07:15:46 +00:00
if ( ! flatpak_mkdir_p ( config_dir , cancellable , error ) )
2015-02-19 21:52:01 +00:00
return NULL ;
return g_object_ref ( dir ) ;
}
2015-03-04 13:40:17 +00:00
2016-05-06 14:03:27 +00:00
struct JobData
{
char * job ;
2015-03-04 13:40:17 +00:00
GMainLoop * main_loop ;
} ;
static void
job_removed_cb ( SystemdManager * manager ,
2016-05-06 14:03:27 +00:00
guint32 id ,
char * job ,
char * unit ,
char * result ,
2015-03-04 13:40:17 +00:00
struct JobData * data )
{
if ( strcmp ( job , data - > job ) = = 0 )
g_main_loop_quit ( data - > main_loop ) ;
}
2016-01-28 10:15:58 +00:00
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_in_transient_unit ( const char * appid , GError * * error )
2016-01-28 10:15:58 +00:00
{
g_autoptr ( GDBusConnection ) conn = NULL ;
g_autofree char * path = NULL ;
g_autofree char * address = NULL ;
g_autofree char * name = NULL ;
g_autofree char * job = NULL ;
2015-03-04 13:40:17 +00:00
SystemdManager * manager = NULL ;
GVariantBuilder builder ;
GVariant * properties = NULL ;
GVariant * aux = NULL ;
guint32 pid ;
GMainContext * main_context = NULL ;
GMainLoop * main_loop = NULL ;
struct JobData data ;
2016-01-28 10:15:58 +00:00
gboolean res = FALSE ;
2015-03-04 13:40:17 +00:00
2016-05-06 14:03:27 +00:00
path = g_strdup_printf ( " /run/user/%d/systemd/private " , getuid ( ) ) ;
2015-03-04 13:40:17 +00:00
if ( ! g_file_test ( path , G_FILE_TEST_EXISTS ) )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error ,
2016-01-28 10:15:58 +00:00
" No systemd user session available, sandboxing not available " ) ;
2015-03-04 13:40:17 +00:00
main_context = g_main_context_new ( ) ;
main_loop = g_main_loop_new ( main_context , FALSE ) ;
g_main_context_push_thread_default ( main_context ) ;
address = g_strconcat ( " unix:path= " , path , NULL ) ;
conn = g_dbus_connection_new_for_address_sync ( address ,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT ,
NULL ,
2016-01-28 10:15:58 +00:00
NULL , error ) ;
2015-03-04 13:40:17 +00:00
if ( ! conn )
2016-01-28 10:15:58 +00:00
goto out ;
2015-03-04 13:40:17 +00:00
manager = systemd_manager_proxy_new_sync ( conn ,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES ,
NULL ,
" /org/freedesktop/systemd1 " ,
2016-01-28 10:15:58 +00:00
NULL , error ) ;
2015-03-04 13:40:17 +00:00
if ( ! manager )
2016-01-28 10:15:58 +00:00
goto out ;
2015-03-04 13:40:17 +00:00
2016-05-09 09:07:53 +00:00
name = g_strdup_printf ( " flatpak-%s-%d.scope " , appid , getpid ( ) ) ;
2015-03-04 13:40:17 +00:00
g_variant_builder_init ( & builder , G_VARIANT_TYPE ( " a(sv) " ) ) ;
pid = getpid ( ) ;
g_variant_builder_add ( & builder , " (sv) " ,
" PIDs " ,
g_variant_new_fixed_array ( G_VARIANT_TYPE ( " u " ) ,
& pid , 1 , sizeof ( guint32 ) )
2016-05-06 14:03:27 +00:00
) ;
2015-03-04 13:40:17 +00:00
properties = g_variant_builder_end ( & builder ) ;
aux = g_variant_new_array ( G_VARIANT_TYPE ( " (sa(sv)) " ) , NULL , 0 ) ;
if ( ! systemd_manager_call_start_transient_unit_sync ( manager ,
name ,
" fail " ,
properties ,
aux ,
& job ,
NULL ,
2016-01-28 10:15:58 +00:00
error ) )
goto out ;
2015-03-04 13:40:17 +00:00
data . job = job ;
data . main_loop = main_loop ;
2016-05-06 14:03:27 +00:00
g_signal_connect ( manager , " job-removed " , G_CALLBACK ( job_removed_cb ) , & data ) ;
2015-03-04 13:40:17 +00:00
g_main_loop_run ( main_loop ) ;
2016-01-28 10:15:58 +00:00
res = TRUE ;
2016-05-06 14:03:27 +00:00
out :
2015-03-04 13:40:17 +00:00
if ( main_context )
{
g_main_context_pop_thread_default ( main_context ) ;
g_main_context_unref ( main_context ) ;
}
if ( main_loop )
g_main_loop_unref ( main_loop ) ;
if ( manager )
g_object_unref ( manager ) ;
2016-01-28 10:15:58 +00:00
return res ;
2015-03-04 13:40:17 +00:00
}
2015-12-07 11:27:53 +00:00
static void
2015-12-07 12:04:45 +00:00
add_font_path_args ( GPtrArray * argv_array )
2015-12-07 11:27:53 +00:00
{
g_autoptr ( GFile ) home = NULL ;
g_autoptr ( GFile ) user_font1 = NULL ;
g_autoptr ( GFile ) user_font2 = NULL ;
2016-06-03 17:28:35 +00:00
if ( g_file_test ( SYSTEM_FONTS_DIR , G_FILE_TEST_EXISTS ) )
{
add_args ( argv_array ,
" --bind " , SYSTEM_FONTS_DIR , " /run/host/fonts " ,
NULL ) ;
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
home = g_file_new_for_path ( g_get_home_dir ( ) ) ;
user_font1 = g_file_resolve_relative_path ( home , " .local/share/fonts " ) ;
user_font2 = g_file_resolve_relative_path ( home , " .fonts " ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
if ( g_file_query_exists ( user_font1 , NULL ) )
2015-12-07 11:27:53 +00:00
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
2016-08-22 08:20:19 +00:00
" --bind " , flatpak_file_get_path_cached ( user_font1 ) , " /run/host/user-fonts " ,
2016-04-29 09:39:39 +00:00
NULL ) ;
2015-12-07 11:27:53 +00:00
}
2015-12-07 12:04:45 +00:00
else if ( g_file_query_exists ( user_font2 , NULL ) )
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
2016-08-22 08:20:19 +00:00
" --bind " , flatpak_file_get_path_cached ( user_font2 ) , " /run/host/user-fonts " ,
2016-04-29 09:39:39 +00:00
NULL ) ;
2015-12-07 12:04:45 +00:00
}
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
static void
2016-05-06 14:37:47 +00:00
add_default_permissions ( FlatpakContext * app_context )
2015-12-07 12:04:45 +00:00
{
2016-05-06 14:37:47 +00:00
flatpak_context_set_session_bus_policy ( app_context ,
2016-06-09 14:03:54 +00:00
" org.freedesktop.portal.* " ,
2016-05-06 14:37:47 +00:00
FLATPAK_POLICY_TALK ) ;
2015-12-07 12:04:45 +00:00
}
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
static FlatpakContext *
2015-12-07 12:04:45 +00:00
compute_permissions ( GKeyFile * app_metadata ,
GKeyFile * runtime_metadata ,
2016-05-06 14:03:27 +00:00
GError * * error )
2015-12-07 12:04:45 +00:00
{
2016-05-06 14:37:47 +00:00
g_autoptr ( FlatpakContext ) app_context = NULL ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
app_context = flatpak_context_new ( ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
add_default_permissions ( app_context ) ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_context_load_metadata ( app_context , runtime_metadata , error ) )
2015-12-07 12:04:45 +00:00
return NULL ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_context_load_metadata ( app_context , app_metadata , error ) )
2015-12-07 12:04:45 +00:00
return NULL ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
return g_steal_pointer ( & app_context ) ;
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
static gboolean
2016-05-06 14:37:47 +00:00
add_app_info_args ( GPtrArray * argv_array ,
2016-05-11 13:33:49 +00:00
GArray * fd_array ,
2016-09-02 11:51:09 +00:00
GFile * app_files ,
2016-05-06 14:37:47 +00:00
const char * app_id ,
const char * runtime_ref ,
FlatpakContext * final_app_context ,
GError * * error )
2015-12-07 12:04:45 +00:00
{
g_autofree char * tmp_path = NULL ;
int fd ;
2015-12-07 11:27:53 +00:00
2016-05-09 09:07:53 +00:00
fd = g_file_open_tmp ( " flatpak-context-XXXXXX " , & tmp_path , NULL ) ;
2015-12-07 12:04:45 +00:00
if ( fd > = 0 )
{
g_autoptr ( GKeyFile ) keyfile = NULL ;
2016-02-03 13:12:36 +00:00
g_autoptr ( GFile ) files = NULL ;
g_autofree char * files_path = NULL ;
2016-04-29 09:39:39 +00:00
g_autofree char * fd_str = NULL ;
2016-05-09 09:07:53 +00:00
g_autofree char * dest = g_strdup_printf ( " /run/user/%d/flatpak-info " , getuid ( ) ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
close ( fd ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
keyfile = g_key_file_new ( ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
g_key_file_set_string ( keyfile , " Application " , " name " , app_id ) ;
g_key_file_set_string ( keyfile , " Application " , " runtime " , runtime_ref ) ;
2015-12-07 11:27:53 +00:00
2016-09-02 11:51:09 +00:00
files_path = g_file_get_path ( app_files ) ;
2016-02-03 13:12:36 +00:00
g_key_file_set_string ( keyfile , " Application " , " app-path " , files_path ) ;
2016-05-06 14:37:47 +00:00
flatpak_context_save_metadata ( final_app_context , keyfile ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
if ( ! g_key_file_save_to_file ( keyfile , tmp_path , error ) )
return FALSE ;
2016-04-29 09:39:39 +00:00
fd = open ( tmp_path , O_RDONLY ) ;
if ( fd = = - 1 )
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Failed to open temp file " ) ) ;
2016-04-29 09:39:39 +00:00
return FALSE ;
}
unlink ( tmp_path ) ;
fd_str = g_strdup_printf ( " %d " , fd ) ;
2016-05-11 13:33:49 +00:00
if ( fd_array )
g_array_append_val ( fd_array , fd ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array , " --file " , fd_str , dest , NULL ) ;
2015-12-07 11:27:53 +00:00
}
2015-12-07 12:04:45 +00:00
return TRUE ;
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
static void
2016-05-25 14:38:50 +00:00
add_monitor_path_args ( gboolean use_session_helper ,
GPtrArray * argv_array )
2015-12-07 12:04:45 +00:00
{
2016-05-09 09:07:53 +00:00
g_autoptr ( AutoFlatpakSessionHelper ) session_helper = NULL ;
2015-12-07 12:04:45 +00:00
g_autofree char * monitor_path = NULL ;
2015-12-07 11:27:53 +00:00
2016-05-25 14:38:50 +00:00
if ( use_session_helper )
{
session_helper =
flatpak_session_helper_proxy_new_for_bus_sync ( G_BUS_TYPE_SESSION ,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS ,
" org.freedesktop.Flatpak " ,
" /org/freedesktop/Flatpak/SessionHelper " ,
NULL , NULL ) ;
}
2015-12-07 11:27:53 +00:00
if ( session_helper & &
2016-05-09 09:07:53 +00:00
flatpak_session_helper_call_request_monitor_sync ( session_helper ,
2015-12-07 11:27:53 +00:00
& monitor_path ,
NULL , NULL ) )
{
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --bind " , monitor_path , " /run/host/monitor " ,
NULL ) ;
add_args ( argv_array ,
" --symlink " , " /run/host/monitor/localtime " , " /etc/localtime " ,
NULL ) ;
2015-12-07 11:27:53 +00:00
}
else
2016-04-29 09:39:39 +00:00
{
2016-05-06 14:03:27 +00:00
char localtime [ PATH_MAX + 1 ] ;
2016-04-29 09:39:39 +00:00
ssize_t symlink_size ;
add_args ( argv_array ,
" --bind " , " /etc/resolv.conf " , " /run/host/monitor/resolv.conf " ,
NULL ) ;
symlink_size = readlink ( " /etc/localtime " , localtime , sizeof ( localtime ) - 1 ) ;
if ( symlink_size > 0 )
{
localtime [ symlink_size ] = 0 ;
add_args ( argv_array ,
" --symlink " , localtime , " /etc/localtime " ,
NULL ) ;
}
else
2016-05-06 14:03:27 +00:00
{
add_args ( argv_array ,
" --bind " , " /etc/localtime " , " /etc/localtime " ,
NULL ) ;
}
2016-04-29 09:39:39 +00:00
}
2015-12-07 12:04:45 +00:00
}
static void
2016-05-06 14:03:27 +00:00
add_document_portal_args ( GPtrArray * argv_array ,
2015-12-07 12:04:45 +00:00
const char * app_id )
{
g_autoptr ( GDBusConnection ) session_bus = NULL ;
g_autofree char * doc_mount_path = NULL ;
2015-12-07 11:27:53 +00:00
session_bus = g_bus_get_sync ( G_BUS_TYPE_SESSION , NULL , NULL ) ;
if ( session_bus )
{
2016-05-06 14:03:27 +00:00
g_autoptr ( GError ) local_error = NULL ;
g_autoptr ( GDBusMessage ) reply = NULL ;
g_autoptr ( GDBusMessage ) msg =
2015-12-07 11:27:53 +00:00
g_dbus_message_new_method_call ( " org.freedesktop.portal.Documents " ,
" /org/freedesktop/portal/documents " ,
" org.freedesktop.portal.Documents " ,
" GetMountPoint " ) ;
g_dbus_message_set_body ( msg , g_variant_new ( " () " ) ) ;
reply =
g_dbus_connection_send_message_with_reply_sync ( session_bus , msg ,
G_DBUS_SEND_MESSAGE_FLAGS_NONE ,
30000 ,
NULL ,
NULL ,
NULL ) ;
if ( reply )
{
if ( g_dbus_message_to_gerror ( reply , & local_error ) )
2016-05-06 14:03:27 +00:00
{
2016-06-24 20:48:28 +00:00
g_message ( " Can't get document portal: %s \n " , local_error - > message ) ;
2016-05-06 14:03:27 +00:00
}
2015-12-07 11:27:53 +00:00
else
2015-12-07 12:04:45 +00:00
{
2016-04-29 09:39:39 +00:00
g_autofree char * src_path = NULL ;
g_autofree char * dst_path = NULL ;
2015-12-07 12:04:45 +00:00
g_variant_get ( g_dbus_message_get_body ( reply ) ,
" (^ay) " , & doc_mount_path ) ;
2016-04-29 09:39:39 +00:00
src_path = g_strdup_printf ( " %s/by-app/%s " ,
doc_mount_path , app_id ) ;
2016-05-06 14:03:27 +00:00
dst_path = g_strdup_printf ( " /run/user/%d/doc " , getuid ( ) ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array , " --bind " , src_path , dst_path , NULL ) ;
2015-12-07 12:04:45 +00:00
}
2015-12-07 11:27:53 +00:00
}
}
2015-12-07 12:04:45 +00:00
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
static void
dbus_spawn_child_setup ( gpointer user_data )
{
int fd = GPOINTER_TO_INT ( user_data ) ;
2016-05-06 14:03:27 +00:00
2015-12-07 12:04:45 +00:00
fcntl ( fd , F_SETFD , 0 ) ;
}
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
static gboolean
add_dbus_proxy_args ( GPtrArray * argv_array ,
GPtrArray * dbus_proxy_argv ,
2016-04-14 14:01:42 +00:00
gboolean enable_logging ,
2016-05-06 14:03:27 +00:00
int sync_fds [ 2 ] ,
GError * * error )
2015-12-07 12:04:45 +00:00
{
char x = ' x ' ;
2016-05-03 08:27:36 +00:00
const char * proxy ;
2016-07-28 13:06:23 +00:00
g_autofree char * commandline = NULL ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
if ( dbus_proxy_argv - > len = = 0 )
return TRUE ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
if ( sync_fds [ 0 ] = = - 1 )
2015-12-07 11:27:53 +00:00
{
2016-04-29 09:39:39 +00:00
g_autofree char * fd_str = NULL ;
if ( pipe ( sync_fds ) < 0 )
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Unable to create sync pipe " ) ) ;
2016-04-29 09:39:39 +00:00
return FALSE ;
}
fd_str = g_strdup_printf ( " %d " , sync_fds [ 0 ] ) ;
add_args ( argv_array , " --sync-fd " , fd_str , NULL ) ;
2015-12-07 11:27:53 +00:00
}
2015-12-07 12:04:45 +00:00
2016-05-06 14:37:47 +00:00
proxy = g_getenv ( " FLATPAK_DBUSPROXY " ) ;
2016-05-03 08:27:36 +00:00
if ( proxy = = NULL )
proxy = DBUSPROXY ;
g_ptr_array_insert ( dbus_proxy_argv , 0 , g_strdup ( proxy ) ) ;
2016-04-29 09:39:39 +00:00
g_ptr_array_insert ( dbus_proxy_argv , 1 , g_strdup_printf ( " --fd=%d " , sync_fds [ 1 ] ) ) ;
2016-04-14 14:01:42 +00:00
if ( enable_logging )
2016-07-28 13:06:23 +00:00
g_ptr_array_add ( dbus_proxy_argv , g_strdup ( " --log " ) ) ;
2015-12-07 12:04:45 +00:00
g_ptr_array_add ( dbus_proxy_argv , NULL ) ; /* NULL terminate */
2016-07-28 13:06:23 +00:00
commandline = g_strjoinv ( " " , ( char * * ) dbus_proxy_argv - > pdata ) ;
2016-08-05 17:33:32 +00:00
g_debug ( " Running '%s' " , commandline ) ;
2016-07-28 13:06:23 +00:00
2015-12-07 12:04:45 +00:00
if ( ! g_spawn_async ( NULL ,
2016-05-06 14:03:27 +00:00
( char * * ) dbus_proxy_argv - > pdata ,
2015-12-07 12:04:45 +00:00
NULL ,
G_SPAWN_SEARCH_PATH ,
dbus_spawn_child_setup ,
2016-04-29 09:39:39 +00:00
GINT_TO_POINTER ( sync_fds [ 1 ] ) ,
2015-12-07 12:04:45 +00:00
NULL , error ) )
2015-12-07 11:27:53 +00:00
{
2016-04-29 09:39:39 +00:00
close ( sync_fds [ 0 ] ) ;
close ( sync_fds [ 1 ] ) ;
2015-12-07 12:04:45 +00:00
return FALSE ;
2015-12-07 11:27:53 +00:00
}
2015-12-07 12:04:45 +00:00
/* Sync with proxy, i.e. wait until its listening on the sockets */
2016-04-29 09:39:39 +00:00
if ( read ( sync_fds [ 0 ] , & x , 1 ) ! = 1 )
2015-12-07 11:27:53 +00:00
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Failed to sync with dbus proxy " ) ) ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
close ( sync_fds [ 0 ] ) ;
close ( sync_fds [ 1 ] ) ;
2015-12-07 12:04:45 +00:00
return FALSE ;
}
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
return TRUE ;
}
# ifdef ENABLE_SECCOMP
static inline void
cleanup_seccomp ( void * p )
{
2016-05-06 14:03:27 +00:00
scmp_filter_ctx * pp = ( scmp_filter_ctx * ) p ;
2016-04-29 09:39:39 +00:00
if ( * pp )
seccomp_release ( * pp ) ;
}
static gboolean
2016-05-06 14:03:27 +00:00
setup_seccomp ( GPtrArray * argv_array ,
2016-05-11 13:41:49 +00:00
GArray * fd_array ,
2016-04-29 09:39:39 +00:00
const char * arch ,
2016-05-06 14:03:27 +00:00
gboolean devel ,
GError * * error )
2016-04-29 09:39:39 +00:00
{
2016-05-06 14:03:27 +00:00
__attribute__ ( ( cleanup ( cleanup_seccomp ) ) ) scmp_filter_ctx seccomp = NULL ;
2016-04-29 09:39:39 +00:00
/**** BEGIN NOTE ON CODE SHARING
*
* There are today a number of different Linux container
* implementations . That will likely continue for long into the
* future . But we can still try to share code , and it ' s important
* to do so because it affects what library and application writers
* can do , and we should support code portability between different
* container tools .
*
2016-05-09 10:21:28 +00:00
* This syscall blacklist is copied from linux - user - chroot , which was in turn
2016-04-29 09:39:39 +00:00
* clearly influenced by the Sandstorm . io blacklist .
*
* If you make any changes here , I suggest sending the changes along
* to other sandbox maintainers . Using the libseccomp list is also
* an appropriate venue :
* https : //groups.google.com/forum/#!topic/libseccomp
*
* A non - exhaustive list of links to container tooling that might
* want to share this blacklist :
*
* https : //github.com/sandstorm-io/sandstorm
* in src / sandstorm / supervisor . c + +
* http : //cgit.freedesktop.org/xdg-app/xdg-app/
2016-05-09 10:21:28 +00:00
* in common / flatpak - run . c
2016-04-29 09:39:39 +00:00
* https : //git.gnome.org/browse/linux-user-chroot
* in src / setup - seccomp . c
*
* * * * END NOTE ON CODE SHARING
*/
2016-05-06 14:03:27 +00:00
struct
{
int scall ;
2016-04-29 09:39:39 +00:00
struct scmp_arg_cmp * arg ;
} syscall_blacklist [ ] = {
/* Block dmesg */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( syslog ) } ,
2016-04-29 09:39:39 +00:00
/* Useless old syscall */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( uselib ) } ,
2016-04-29 09:39:39 +00:00
/* Don't allow you to switch to bsd emulation or whatnot */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( personality ) } ,
2016-04-29 09:39:39 +00:00
/* Don't allow disabling accounting */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( acct ) } ,
2016-04-29 09:39:39 +00:00
/* 16-bit code is unnecessary in the sandbox, and modify_ldt is a
historic source of interesting information leaks . */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( modify_ldt ) } ,
2016-04-29 09:39:39 +00:00
/* Don't allow reading current quota use */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( quotactl ) } ,
2016-04-29 09:39:39 +00:00
/* Scary VM/NUMA ops */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( move_pages ) } ,
{ SCMP_SYS ( mbind ) } ,
{ SCMP_SYS ( get_mempolicy ) } ,
{ SCMP_SYS ( set_mempolicy ) } ,
{ SCMP_SYS ( migrate_pages ) } ,
2016-04-29 09:39:39 +00:00
/* Don't allow subnamespace setups: */
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( unshare ) } ,
{ SCMP_SYS ( mount ) } ,
{ SCMP_SYS ( pivot_root ) } ,
{ SCMP_SYS ( clone ) , & SCMP_A0 ( SCMP_CMP_MASKED_EQ , CLONE_NEWUSER , CLONE_NEWUSER ) } ,
2016-04-29 09:39:39 +00:00
} ;
2016-05-06 14:03:27 +00:00
struct
{
int scall ;
2016-04-29 09:39:39 +00:00
struct scmp_arg_cmp * arg ;
} syscall_nondevel_blacklist [ ] = {
/* Profiling operations; we expect these to be done by tools from outside
* the sandbox . In particular perf has been the source of many CVEs .
*/
2016-05-06 14:03:27 +00:00
{ SCMP_SYS ( perf_event_open ) } ,
{ SCMP_SYS ( ptrace ) }
2016-04-29 09:39:39 +00:00
} ;
/* Blacklist all but unix, inet, inet6 and netlink */
int socket_family_blacklist [ ] = {
AF_AX25 ,
AF_IPX ,
AF_APPLETALK ,
AF_NETROM ,
AF_BRIDGE ,
AF_ATMPVC ,
AF_X25 ,
AF_ROSE ,
AF_DECnet ,
AF_NETBEUI ,
AF_SECURITY ,
AF_KEY ,
AF_NETLINK + 1 , /* Last gets CMP_GE, so order is important */
} ;
int i , r ;
glnx_fd_close int fd = - 1 ;
g_autofree char * fd_str = NULL ;
g_autofree char * path = NULL ;
seccomp = seccomp_init ( SCMP_ACT_ALLOW ) ;
if ( ! seccomp )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Initialize seccomp failed " ) ;
2016-04-29 09:39:39 +00:00
if ( arch ! = NULL )
{
uint32_t arch_id = 0 ;
if ( strcmp ( arch , " i386 " ) = = 0 )
arch_id = SCMP_ARCH_X86 ;
else if ( strcmp ( arch , " x86_64 " ) = = 0 )
arch_id = SCMP_ARCH_X86_64 ;
2016-05-16 09:12:29 +00:00
else if ( strcmp ( arch , " arm " ) = = 0 )
arch_id = SCMP_ARCH_ARM ;
2016-05-20 09:07:34 +00:00
# ifdef SCMP_ARCH_AARCH64
2016-05-16 09:12:29 +00:00
else if ( strcmp ( arch , " aarch64 " ) = = 0 )
arch_id = SCMP_ARCH_AARCH64 ;
2016-05-20 09:07:34 +00:00
# endif
2016-04-29 09:39:39 +00:00
/* We only really need to handle arches on multiarch systems.
* If only one arch is supported the default is fine */
if ( arch_id ! = 0 )
{
/* This *adds* the target arch, instead of replacing the
native one . This is not ideal , because we ' d like to only
allow the target arch , but we can ' t really disallow the
2016-05-09 09:07:53 +00:00
native arch at this point , because then bubblewrap
2016-05-27 06:46:11 +00:00
couldn ' t continue running . */
2016-04-29 09:39:39 +00:00
r = seccomp_arch_add ( seccomp , arch_id ) ;
if ( r < 0 & & r ! = - EEXIST )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Failed to add architecture to seccomp filter " ) ;
2016-04-29 09:39:39 +00:00
}
}
/* TODO: Should we filter the kernel keyring syscalls in some way?
* We do want them to be used by desktop apps , but they could also perhaps
* leak system stuff or secrets from other apps .
*/
for ( i = 0 ; i < G_N_ELEMENTS ( syscall_blacklist ) ; i + + )
{
int scall = syscall_blacklist [ i ] . scall ;
if ( syscall_blacklist [ i ] . arg )
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add ( seccomp , SCMP_ACT_ERRNO ( EPERM ) , scall , 1 , * syscall_blacklist [ i ] . arg ) ;
2016-04-29 09:39:39 +00:00
else
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add ( seccomp , SCMP_ACT_ERRNO ( EPERM ) , scall , 0 ) ;
2016-04-29 09:39:39 +00:00
if ( r < 0 & & r = = - EFAULT /* unknown syscall */ )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Failed to block syscall %d " , scall ) ;
2016-04-29 09:39:39 +00:00
}
if ( ! devel )
{
for ( i = 0 ; i < G_N_ELEMENTS ( syscall_nondevel_blacklist ) ; i + + )
{
int scall = syscall_nondevel_blacklist [ i ] . scall ;
if ( syscall_nondevel_blacklist [ i ] . arg )
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add ( seccomp , SCMP_ACT_ERRNO ( EPERM ) , scall , 1 , * syscall_nondevel_blacklist [ i ] . arg ) ;
2016-04-29 09:39:39 +00:00
else
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add ( seccomp , SCMP_ACT_ERRNO ( EPERM ) , scall , 0 ) ;
2016-04-29 09:39:39 +00:00
if ( r < 0 & & r = = - EFAULT /* unknown syscall */ )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Failed to block syscall %d " , scall ) ;
2016-04-29 09:39:39 +00:00
}
}
/* Socket filtering doesn't work on e.g. i386, so ignore failures here
* However , we need to user seccomp_rule_add_exact to avoid libseccomp doing
* something else : https : //github.com/seccomp/libseccomp/issues/8 */
for ( i = 0 ; i < G_N_ELEMENTS ( socket_family_blacklist ) ; i + + )
{
int family = socket_family_blacklist [ i ] ;
if ( i = = G_N_ELEMENTS ( socket_family_blacklist ) - 1 )
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add_exact ( seccomp , SCMP_ACT_ERRNO ( EAFNOSUPPORT ) , SCMP_SYS ( socket ) , 1 , SCMP_A0 ( SCMP_CMP_GE , family ) ) ;
2016-04-29 09:39:39 +00:00
else
2016-05-06 14:03:27 +00:00
r = seccomp_rule_add_exact ( seccomp , SCMP_ACT_ERRNO ( EAFNOSUPPORT ) , SCMP_SYS ( socket ) , 1 , SCMP_A0 ( SCMP_CMP_EQ , family ) ) ;
2016-04-29 09:39:39 +00:00
}
2016-05-09 09:07:53 +00:00
fd = g_file_open_tmp ( " flatpak-seccomp-XXXXXX " , & path , error ) ;
2016-04-29 09:39:39 +00:00
if ( fd = = - 1 )
return FALSE ;
unlink ( path ) ;
if ( seccomp_export_bpf ( seccomp , fd ) ! = 0 )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Failed to export bpf " ) ;
2016-04-29 09:39:39 +00:00
lseek ( fd , 0 , SEEK_SET ) ;
fd_str = g_strdup_printf ( " %d " , fd ) ;
2016-05-11 13:41:49 +00:00
if ( fd_array )
g_array_append_val ( fd_array , fd ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --seccomp " , fd_str ,
NULL ) ;
fd = - 1 ; /* Don't close on success */
return TRUE ;
}
# endif
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_setup_base_argv ( GPtrArray * argv_array ,
2016-05-11 13:33:49 +00:00
GArray * fd_array ,
2016-05-06 14:37:47 +00:00
GFile * runtime_files ,
GFile * app_id_dir ,
const char * arch ,
FlatpakRunFlags flags ,
GError * * error )
2016-04-29 09:39:39 +00:00
{
const char * usr_links [ ] = { " lib " , " lib32 " , " lib64 " , " bin " , " sbin " } ;
g_autofree char * run_dir = g_strdup_printf ( " /run/user/%d " , getuid ( ) ) ;
int i ;
int passwd_fd = - 1 ;
g_autofree char * passwd_fd_str = NULL ;
g_autofree char * passwd_contents = NULL ;
int group_fd = - 1 ;
g_autofree char * group_fd_str = NULL ;
g_autofree char * group_contents = NULL ;
struct group * g = getgrgid ( getgid ( ) ) ;
2016-05-06 14:03:27 +00:00
2016-04-29 09:39:39 +00:00
g_autoptr ( GFile ) etc = NULL ;
passwd_contents = g_strdup_printf ( " %s:x:%d:%d:%s:%s:%s \n "
" nfsnobody:x:65534:65534:Unmapped user:/:/sbin/nologin \n " ,
g_get_user_name ( ) ,
getuid ( ) , getgid ( ) ,
g_get_real_name ( ) ,
g_get_home_dir ( ) ,
DEFAULT_SHELL ) ;
if ( ( passwd_fd = create_tmp_fd ( passwd_contents , - 1 , error ) ) < 0 )
return FALSE ;
passwd_fd_str = g_strdup_printf ( " %d " , passwd_fd ) ;
2016-05-11 13:33:49 +00:00
if ( fd_array )
g_array_append_val ( fd_array , passwd_fd ) ;
2016-04-29 09:39:39 +00:00
group_contents = g_strdup_printf ( " %s:x:%d:%s \n "
2016-05-06 14:03:27 +00:00
" nfsnobody:x:65534: \n " ,
g - > gr_name ,
getgid ( ) , g_get_user_name ( ) ) ;
2016-04-29 09:39:39 +00:00
if ( ( group_fd = create_tmp_fd ( group_contents , - 1 , error ) ) < 0 )
return FALSE ;
group_fd_str = g_strdup_printf ( " %d " , group_fd ) ;
2016-05-11 13:33:49 +00:00
if ( fd_array )
g_array_append_val ( fd_array , group_fd ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
" --unshare-pid " ,
2016-05-23 07:10:39 +00:00
" --unshare-user-try " ,
2016-04-29 09:39:39 +00:00
" --proc " , " /proc " ,
" --dir " , " /tmp " ,
2016-06-15 23:31:17 +00:00
" --dir " , " /var/tmp " ,
2016-04-29 09:39:39 +00:00
" --dir " , " /run/host " ,
" --dir " , run_dir ,
" --setenv " , " XDG_RUNTIME_DIR " , run_dir ,
" --symlink " , " /run " , " /var/run " ,
" --ro-bind " , " /sys/block " , " /sys/block " ,
" --ro-bind " , " /sys/bus " , " /sys/bus " ,
" --ro-bind " , " /sys/class " , " /sys/class " ,
" --ro-bind " , " /sys/dev " , " /sys/dev " ,
" --ro-bind " , " /sys/devices " , " /sys/devices " ,
" --bind-data " , passwd_fd_str , " /etc/passwd " ,
" --bind-data " , group_fd_str , " /etc/group " ,
" --symlink " , " /run/host/monitor/resolv.conf " , " /etc/resolv.conf " ,
/* Always create a homedir to start from, although it may be covered later */
" --dir " , g_get_home_dir ( ) ,
NULL ) ;
if ( g_file_test ( " /etc/machine-id " , G_FILE_TEST_EXISTS ) )
add_args ( argv_array , " --bind " , " /etc/machine-id " , " /etc/machine-id " , NULL ) ;
else if ( g_file_test ( " /var/lib/dbus/machine-id " , G_FILE_TEST_EXISTS ) )
add_args ( argv_array , " --bind " , " /var/lib/dbus/machine-id " , " /etc/machine-id " , NULL ) ;
etc = g_file_get_child ( runtime_files , " etc " ) ;
if ( g_file_query_exists ( etc , NULL ) )
{
g_auto ( GLnxDirFdIterator ) dfd_iter = { 0 , } ;
struct dirent * dent ;
2016-05-06 14:03:27 +00:00
char path_buffer [ PATH_MAX + 1 ] ;
2016-04-29 09:39:39 +00:00
ssize_t symlink_size ;
2016-08-22 08:20:19 +00:00
glnx_dirfd_iterator_init_at ( AT_FDCWD , flatpak_file_get_path_cached ( etc ) , FALSE , & dfd_iter , NULL ) ;
2016-04-29 09:39:39 +00:00
while ( TRUE )
{
g_autofree char * src = NULL ;
g_autofree char * dest = NULL ;
if ( ! glnx_dirfd_iterator_next_dent_ensure_dtype ( & dfd_iter , & dent , NULL , NULL ) | | dent = = NULL )
break ;
if ( strcmp ( dent - > d_name , " passwd " ) = = 0 | |
strcmp ( dent - > d_name , " group " ) = = 0 | |
strcmp ( dent - > d_name , " machine-id " ) = = 0 | |
strcmp ( dent - > d_name , " resolv.conf " ) = = 0 | |
strcmp ( dent - > d_name , " localtime " ) = = 0 )
continue ;
2016-08-22 08:20:19 +00:00
src = g_build_filename ( flatpak_file_get_path_cached ( etc ) , dent - > d_name , NULL ) ;
2016-04-29 09:39:39 +00:00
dest = g_build_filename ( " /etc " , dent - > d_name , NULL ) ;
if ( dent - > d_type = = DT_LNK )
{
symlink_size = readlinkat ( dfd_iter . fd , dent - > d_name , path_buffer , sizeof ( path_buffer ) - 1 ) ;
if ( symlink_size < 0 )
{
glnx_set_error_from_errno ( error ) ;
return FALSE ;
}
path_buffer [ symlink_size ] = 0 ;
add_args ( argv_array , " --symlink " , path_buffer , dest , NULL ) ;
}
else
2016-05-06 14:03:27 +00:00
{
add_args ( argv_array , " --bind " , src , dest , NULL ) ;
}
2016-04-29 09:39:39 +00:00
}
}
if ( app_id_dir ! = NULL )
{
g_autoptr ( GFile ) app_cache_dir = g_file_get_child ( app_id_dir , " cache " ) ;
g_autoptr ( GFile ) app_data_dir = g_file_get_child ( app_id_dir , " data " ) ;
g_autoptr ( GFile ) app_config_dir = g_file_get_child ( app_id_dir , " config " ) ;
add_args ( argv_array ,
/* These are nice to have as a fixed path */
2016-08-22 08:20:19 +00:00
" --bind " , flatpak_file_get_path_cached ( app_cache_dir ) , " /var/cache " ,
" --bind " , flatpak_file_get_path_cached ( app_data_dir ) , " /var/data " ,
" --bind " , flatpak_file_get_path_cached ( app_config_dir ) , " /var/config " ,
2016-04-29 09:39:39 +00:00
NULL ) ;
}
2016-05-06 14:03:27 +00:00
for ( i = 0 ; i < G_N_ELEMENTS ( usr_links ) ; i + + )
2016-04-29 09:39:39 +00:00
{
const char * subdir = usr_links [ i ] ;
g_autoptr ( GFile ) runtime_subdir = g_file_get_child ( runtime_files , subdir ) ;
if ( g_file_query_exists ( runtime_subdir , NULL ) )
{
g_autofree char * link = g_strconcat ( " usr/ " , subdir , NULL ) ;
g_autofree char * dest = g_strconcat ( " / " , subdir , NULL ) ;
add_args ( argv_array ,
" --symlink " , link , dest ,
NULL ) ;
}
}
# ifdef ENABLE_SECCOMP
if ( ! setup_seccomp ( argv_array ,
2016-05-11 13:41:49 +00:00
fd_array ,
2016-04-29 09:39:39 +00:00
arch ,
2016-05-06 14:37:47 +00:00
( flags & FLATPAK_RUN_FLAG_DEVEL ) ! = 0 ,
2016-04-29 09:39:39 +00:00
error ) )
return FALSE ;
# endif
2015-12-07 11:27:53 +00:00
2016-05-25 14:38:50 +00:00
add_monitor_path_args ( ( flags & FLATPAK_RUN_FLAG_NO_SESSION_HELPER ) = = 0 , argv_array ) ;
2015-12-07 12:04:45 +00:00
return TRUE ;
}
2015-12-07 11:27:53 +00:00
2016-05-06 14:03:27 +00:00
gchar *
2016-04-29 09:39:39 +00:00
join_args ( GPtrArray * argv_array , gsize * len_out )
{
gchar * string ;
gchar * ptr ;
gint i ;
gsize len = 0 ;
for ( i = 0 ; i < argv_array - > len ; i + + )
len + = strlen ( argv_array - > pdata [ i ] ) + 1 ;
string = g_new ( gchar , len ) ;
* string = 0 ;
ptr = string ;
for ( i = 0 ; i < argv_array - > len ; i + + )
ptr = g_stpcpy ( ptr , argv_array - > pdata [ i ] ) + 1 ;
* len_out = len ;
return string ;
}
2016-05-11 13:14:11 +00:00
static void
clear_fd ( gpointer data )
{
int * fd_p = data ;
if ( fd_p ! = NULL & & * fd_p ! = - 1 )
close ( * fd_p ) ;
}
static void
child_setup ( gpointer user_data )
{
GArray * fd_array = user_data ;
2016-05-11 13:33:49 +00:00
int i ;
2016-05-11 13:14:11 +00:00
/* If no fd_array was specified, don't care. */
if ( fd_array = = NULL )
return ;
2016-05-11 13:33:49 +00:00
/* Otherwise, mark not - close-on-exec all the fds in the array */
for ( i = 0 ; i < fd_array - > len ; i + + )
fcntl ( g_array_index ( fd_array , int , i ) , F_SETFD , 0 ) ;
2016-05-11 13:14:11 +00:00
}
2015-12-07 12:04:45 +00:00
gboolean
2016-05-06 14:37:47 +00:00
flatpak_run_app ( const char * app_ref ,
FlatpakDeploy * app_deploy ,
FlatpakContext * extra_context ,
const char * custom_runtime ,
const char * custom_runtime_version ,
FlatpakRunFlags flags ,
const char * custom_command ,
char * args [ ] ,
int n_args ,
GCancellable * cancellable ,
GError * * error )
{
g_autoptr ( FlatpakDeploy ) runtime_deploy = NULL ;
2015-12-07 12:04:45 +00:00
g_autoptr ( GFile ) app_files = NULL ;
g_autoptr ( GFile ) runtime_files = NULL ;
g_autoptr ( GFile ) app_id_dir = NULL ;
2016-01-12 08:57:20 +00:00
g_autofree char * default_runtime = NULL ;
2015-12-07 12:04:45 +00:00
g_autofree char * default_command = NULL ;
g_autofree char * runtime_ref = NULL ;
2016-04-29 09:39:39 +00:00
int sync_fds [ 2 ] = { - 1 , - 1 } ;
2015-12-07 12:04:45 +00:00
g_autoptr ( GKeyFile ) metakey = NULL ;
g_autoptr ( GKeyFile ) runtime_metakey = NULL ;
g_autoptr ( GPtrArray ) argv_array = NULL ;
2016-05-11 13:14:11 +00:00
g_autoptr ( GArray ) fd_array = NULL ;
2016-04-29 09:39:39 +00:00
g_autoptr ( GPtrArray ) real_argv_array = NULL ;
2015-12-07 12:04:45 +00:00
g_auto ( GStrv ) envp = NULL ;
2016-01-29 07:50:11 +00:00
g_autoptr ( GPtrArray ) session_bus_proxy_argv = NULL ;
g_autoptr ( GPtrArray ) system_bus_proxy_argv = NULL ;
2015-12-07 12:04:45 +00:00
const char * command = " /bin/sh " ;
2016-01-12 08:57:20 +00:00
g_autoptr ( GError ) my_error = NULL ;
g_auto ( GStrv ) runtime_parts = NULL ;
2015-12-07 12:04:45 +00:00
int i ;
2016-05-06 14:37:47 +00:00
g_autoptr ( FlatpakContext ) app_context = NULL ;
g_autoptr ( FlatpakContext ) overrides = NULL ;
2015-12-07 12:04:45 +00:00
g_auto ( GStrv ) app_ref_parts = NULL ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
app_ref_parts = flatpak_decompose_ref ( app_ref , error ) ;
2015-12-07 12:04:45 +00:00
if ( app_ref_parts = = NULL )
return FALSE ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
metakey = flatpak_deploy_get_metadata ( app_deploy ) ;
2015-12-07 11:27:53 +00:00
2015-12-07 12:04:45 +00:00
argv_array = g_ptr_array_new_with_free_func ( g_free ) ;
2016-05-11 13:14:11 +00:00
fd_array = g_array_new ( FALSE , TRUE , sizeof ( int ) ) ;
g_array_set_clear_func ( fd_array , clear_fd ) ;
2016-01-29 07:50:11 +00:00
session_bus_proxy_argv = g_ptr_array_new_with_free_func ( g_free ) ;
system_bus_proxy_argv = g_ptr_array_new_with_free_func ( g_free ) ;
2015-12-07 12:04:45 +00:00
2016-01-12 08:57:20 +00:00
default_runtime = g_key_file_get_string ( metakey , " Application " ,
2016-05-06 14:37:47 +00:00
( flags & FLATPAK_RUN_FLAG_DEVEL ) ! = 0 ? " sdk " : " runtime " ,
2016-01-12 08:57:20 +00:00
& my_error ) ;
if ( my_error )
{
g_propagate_error ( error , g_steal_pointer ( & my_error ) ) ;
return FALSE ;
}
runtime_parts = g_strsplit ( default_runtime , " / " , 0 ) ;
if ( g_strv_length ( runtime_parts ) ! = 3 )
2016-05-06 14:37:47 +00:00
return flatpak_fail ( error , " Wrong number of components in runtime %s " , default_runtime ) ;
2016-01-12 08:57:20 +00:00
2015-12-07 12:04:45 +00:00
if ( custom_runtime )
{
2016-01-12 08:57:20 +00:00
g_auto ( GStrv ) custom_runtime_parts = g_strsplit ( custom_runtime , " / " , 0 ) ;
for ( i = 0 ; i < 3 & & custom_runtime_parts [ i ] ! = NULL ; i + + )
2015-12-07 12:34:50 +00:00
{
2016-01-12 08:57:20 +00:00
if ( strlen ( custom_runtime_parts [ i ] ) > 0 )
{
g_free ( runtime_parts [ i ] ) ;
runtime_parts [ i ] = g_steal_pointer ( & custom_runtime_parts [ i ] ) ;
}
2015-12-07 12:34:50 +00:00
}
2015-12-07 11:27:53 +00:00
}
2016-01-12 08:57:20 +00:00
if ( custom_runtime_version )
{
g_free ( runtime_parts [ 2 ] ) ;
runtime_parts [ 2 ] = g_strdup ( custom_runtime_version ) ;
}
2016-05-06 14:37:47 +00:00
runtime_ref = flatpak_compose_ref ( FALSE ,
2016-01-12 08:57:20 +00:00
runtime_parts [ 0 ] ,
runtime_parts [ 2 ] ,
runtime_parts [ 1 ] ,
error ) ;
if ( runtime_ref = = NULL )
return FALSE ;
2015-12-07 12:04:45 +00:00
2016-05-06 14:37:47 +00:00
runtime_deploy = flatpak_find_deploy_for_ref ( runtime_ref , cancellable , error ) ;
2015-12-07 12:04:45 +00:00
if ( runtime_deploy = = NULL )
return FALSE ;
2016-05-06 14:37:47 +00:00
runtime_metakey = flatpak_deploy_get_metadata ( runtime_deploy ) ;
2015-12-07 12:04:45 +00:00
app_context = compute_permissions ( metakey , runtime_metakey , error ) ;
if ( app_context = = NULL )
return FALSE ;
2016-05-06 14:37:47 +00:00
overrides = flatpak_deploy_get_overrides ( app_deploy ) ;
flatpak_context_merge ( app_context , overrides ) ;
2015-12-07 12:04:45 +00:00
2015-12-07 12:34:50 +00:00
if ( extra_context )
2016-05-06 14:37:47 +00:00
flatpak_context_merge ( app_context , extra_context ) ;
2015-12-07 12:04:45 +00:00
2016-05-06 14:37:47 +00:00
runtime_files = flatpak_deploy_get_files ( runtime_deploy ) ;
app_files = flatpak_deploy_get_files ( app_deploy ) ;
2016-04-29 09:39:39 +00:00
2016-05-06 14:37:47 +00:00
if ( ( app_id_dir = flatpak_ensure_data_dir ( app_ref_parts [ 1 ] , cancellable , error ) ) = = NULL )
2016-05-06 14:03:27 +00:00
return FALSE ;
2016-04-29 09:39:39 +00:00
envp = g_get_environ ( ) ;
2016-05-06 14:37:47 +00:00
envp = flatpak_run_apply_env_default ( envp ) ;
envp = flatpak_run_apply_env_vars ( envp , app_context ) ;
envp = flatpak_run_apply_env_appid ( envp , app_id_dir ) ;
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
2016-08-22 08:20:19 +00:00
" --ro-bind " , flatpak_file_get_path_cached ( runtime_files ) , " /usr " ,
2016-04-29 09:39:39 +00:00
" --lock-file " , " /usr/.ref " ,
2016-08-22 08:20:19 +00:00
" --ro-bind " , flatpak_file_get_path_cached ( app_files ) , " /app " ,
2016-04-29 09:39:39 +00:00
" --lock-file " , " /app/.ref " ,
NULL ) ;
2016-05-11 13:33:49 +00:00
if ( ! flatpak_run_setup_base_argv ( argv_array , fd_array , runtime_files , app_id_dir , app_ref_parts [ 2 ] , flags , error ) )
2015-12-07 12:04:45 +00:00
return FALSE ;
2016-09-02 11:51:09 +00:00
if ( ! add_app_info_args ( argv_array , fd_array , app_files , app_ref_parts [ 1 ] , runtime_ref , app_context , error ) )
2015-12-07 12:04:45 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
if ( ! flatpak_run_add_extension_args ( argv_array , metakey , app_ref , cancellable , error ) )
2016-04-29 09:39:39 +00:00
return FALSE ;
2015-12-07 12:04:45 +00:00
2016-05-06 14:37:47 +00:00
if ( ! flatpak_run_add_extension_args ( argv_array , runtime_metakey , runtime_ref , cancellable , error ) )
2016-04-29 09:39:39 +00:00
return FALSE ;
2015-12-07 12:04:45 +00:00
add_document_portal_args ( argv_array , app_ref_parts [ 1 ] ) ;
2016-05-11 13:14:11 +00:00
flatpak_run_add_environment_args ( argv_array , fd_array , & envp ,
2016-01-29 07:50:11 +00:00
session_bus_proxy_argv ,
system_bus_proxy_argv ,
2015-12-07 12:04:45 +00:00
app_ref_parts [ 1 ] , app_context , app_id_dir ) ;
2016-06-28 13:05:01 +00:00
flatpak_run_add_journal_args ( argv_array ) ;
2015-12-07 12:04:45 +00:00
add_font_path_args ( argv_array ) ;
/* Must run this before spawning the dbus proxy, to ensure it
ends up in the app cgroup */
2016-07-01 17:33:53 +00:00
if ( ! option_no_desktop & & ! flatpak_run_in_transient_unit ( app_ref_parts [ 1 ] , error ) )
2016-01-28 10:15:58 +00:00
return FALSE ;
2015-12-07 12:04:45 +00:00
2016-05-06 14:37:47 +00:00
if ( ! add_dbus_proxy_args ( argv_array , session_bus_proxy_argv , ( flags & FLATPAK_RUN_FLAG_LOG_SESSION_BUS ) ! = 0 , sync_fds , error ) )
2016-01-29 07:50:11 +00:00
return FALSE ;
2016-05-06 14:37:47 +00:00
if ( ! add_dbus_proxy_args ( argv_array , system_bus_proxy_argv , ( flags & FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS ) ! = 0 , sync_fds , error ) )
2015-12-07 12:04:45 +00:00
return FALSE ;
2016-04-29 09:39:39 +00:00
if ( sync_fds [ 1 ] ! = - 1 )
close ( sync_fds [ 1 ] ) ;
2015-12-07 12:04:45 +00:00
2016-04-29 09:39:39 +00:00
add_args ( argv_array ,
2016-05-09 09:07:53 +00:00
/* Not in base, because we don't want this for flatpak build */
2016-04-29 09:39:39 +00:00
" --symlink " , " /app/lib/debug/source " , " /run/build " ,
" --symlink " , " /usr/lib/debug/source " , " /run/build-runtime " ,
NULL ) ;
2015-12-07 12:04:45 +00:00
if ( custom_command )
2016-05-06 14:03:27 +00:00
{
command = custom_command ;
}
2015-12-07 12:04:45 +00:00
else
2015-12-07 12:34:50 +00:00
{
default_command = g_key_file_get_string ( metakey , " Application " , " command " , & my_error ) ;
if ( my_error )
{
g_propagate_error ( error , g_steal_pointer ( & my_error ) ) ;
return FALSE ;
}
command = default_command ;
}
2015-12-07 12:04:45 +00:00
2016-04-29 09:39:39 +00:00
real_argv_array = g_ptr_array_new_with_free_func ( g_free ) ;
2016-05-06 14:37:47 +00:00
g_ptr_array_add ( real_argv_array , g_strdup ( flatpak_get_bwrap ( ) ) ) ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
{
gsize len ;
int arg_fd ;
g_autofree char * arg_fd_str = NULL ;
g_autofree char * args = join_args ( argv_array , & len ) ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
arg_fd = create_tmp_fd ( args , len , error ) ;
if ( arg_fd < 0 )
return FALSE ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
arg_fd_str = g_strdup_printf ( " %d " , arg_fd ) ;
2016-05-11 13:23:29 +00:00
g_array_append_val ( fd_array , arg_fd ) ;
2015-12-07 11:27:53 +00:00
2016-04-29 09:39:39 +00:00
add_args ( real_argv_array ,
" --args " , arg_fd_str ,
NULL ) ;
}
g_ptr_array_add ( real_argv_array , g_strdup ( command ) ) ;
for ( i = 0 ; i < n_args ; i + + )
g_ptr_array_add ( real_argv_array , g_strdup ( args [ i ] ) ) ;
g_ptr_array_add ( real_argv_array , NULL ) ;
2015-12-07 11:27:53 +00:00
2016-05-06 14:37:47 +00:00
if ( ( flags & FLATPAK_RUN_FLAG_BACKGROUND ) ! = 0 )
2015-12-07 11:27:53 +00:00
{
if ( ! g_spawn_async ( NULL ,
2016-05-06 14:03:27 +00:00
( char * * ) real_argv_array - > pdata ,
2015-12-07 11:27:53 +00:00
envp ,
2016-05-11 13:33:49 +00:00
G_SPAWN_DEFAULT ,
2016-07-28 22:24:43 +00:00
child_setup , fd_array ,
2015-12-07 11:27:53 +00:00
NULL ,
error ) )
return FALSE ;
}
else
{
2016-05-06 14:37:47 +00:00
if ( execvpe ( flatpak_get_bwrap ( ) , ( char * * ) real_argv_array - > pdata , envp ) = = - 1 )
2015-12-07 11:27:53 +00:00
{
2016-07-23 17:59:45 +00:00
g_set_error_literal ( error , G_IO_ERROR , g_io_error_from_errno ( errno ) ,
_ ( " Unable to start app " ) ) ;
2015-12-07 11:27:53 +00:00
return FALSE ;
}
/* Not actually reached... */
}
return TRUE ;
}