Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'jb48441' into 'master'
Limit dynamic modes to device owner

See merge request mer-core/usb-moded!55
  • Loading branch information
Tomin1 committed Jan 17, 2020
2 parents 3142bf0 + 6e98e56 commit e692ad5
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 30 deletions.
9 changes: 9 additions & 0 deletions configure.ac
Expand Up @@ -49,6 +49,14 @@ AC_ARG_ENABLE([mer_ssu], AS_HELP_STRING([--enable-mer-ssu], [Enable MER SSU @<:@
esac],[mer_ssu=false])
AM_CONDITIONAL([USE_MER_SSU], [test x$mer_ssu = xtrue])

AC_ARG_ENABLE([sailfish_access_control], AS_HELP_STRING([--enable-sailfish-access-control], [Enable Sailfish Access Control @<:@default=false@:>@]),
[case "${enableval}" in
yes) sailfish_access_control=true ; CFLAGS="-DSAILFISH_ACCESS_CONTROL $CFLAGS" ;;
no) sailfish_access_control=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-sailfish-access-control]) ;;
esac],[sailfish_access_control=false])
AM_CONDITIONAL([SAILFISH_ACCESS_CONTROL], [test x$sailfish_access_control = xtrue])

AC_ARG_ENABLE([app_sync], AS_HELP_STRING([--enable-app-sync], [Enable application syncing @<:@default=true@:>@]),
[case "${enableval}" in
yes) app_sync=true ; CFLAGS="-DAPP_SYNC $CFLAGS" ;;
Expand Down Expand Up @@ -100,6 +108,7 @@ PKG_CHECK_MODULES([USB_MODED], [
ssu-sysinfo
libsystemd
dsme
sailfishaccesscontrol
])

AC_SUBST(USB_MODED_LIBS)
Expand Down
3 changes: 2 additions & 1 deletion rpm/usb-moded.spec
Expand Up @@ -17,6 +17,7 @@ BuildRequires: doxygen
BuildRequires: pkgconfig(libsystemd)
BuildRequires: pkgconfig(ssu-sysinfo)
BuildRequires: pkgconfig(dsme) >= 0.65.0
BuildRequires: pkgconfig(sailfishaccesscontrol)

Requires: lsof
Requires: usb-moded-configs
Expand Down Expand Up @@ -327,7 +328,7 @@ when the UI fails.

%build
test -e Makefile || (%autogen)
test -e Makefile || (%configure --enable-app-sync --enable-meegodevlock --enable-debug --enable-connman --enable-systemd --enable-mer-ssu)
test -e Makefile || (%configure --enable-app-sync --enable-meegodevlock --enable-debug --enable-connman --enable-systemd --enable-mer-ssu --enable-sailfish-access-control)
make all doc %{?_smp_mflags}

%install
Expand Down
5 changes: 5 additions & 0 deletions src/Makefile.am
Expand Up @@ -80,6 +80,11 @@ usb_moded_SOURCES += \
usb_moded-appsync-dbus-private.h
endif

if SAILFISH_ACCESS_CONTROL
usb_moded_CPPFLAGS += `pkg-config --cflags sailfishaccesscontrol`
usb_moded_LDFLAGS += `pkg-config --libs sailfishaccesscontrol`
endif

usb_moded_util_CPPFLAGS = \
$(USB_MODED_CFLAGS)

Expand Down
3 changes: 3 additions & 0 deletions src/com.meego.usb_moded.xml
Expand Up @@ -36,6 +36,9 @@
<method name="get_available_modes">
<arg name="modes" type="s" direction="out"/>
</method>
<method name="get_available_modes_for_user">
<arg name="modes" type="s" direction="out"/>
</method>
<method name="hide_mode">
<arg name="mode" type="s" direction="in"/>
<arg name="mode" type="s" direction="out"/>
Expand Down
14 changes: 10 additions & 4 deletions src/usb_moded-common.c
Expand Up @@ -61,7 +61,7 @@ bool common_msleep_ (const char *file, int line, co
static bool common_mode_in_list (const char *mode, char *const *modes);
bool common_modename_is_internal (const char *modename);
int common_valid_mode (const char *mode);
gchar *common_get_mode_list (mode_list_type_t type);
gchar *common_get_mode_list (mode_list_type_t type, uid_t uid);

/* ========================================================================= *
* Functions
Expand Down Expand Up @@ -205,7 +205,7 @@ void common_send_supported_modes_signal(void)
{
LOG_REGISTER_CONTEXT;

gchar *mode_list = common_get_mode_list(SUPPORTED_MODES_LIST);
gchar *mode_list = common_get_mode_list(SUPPORTED_MODES_LIST, 0);
umdbus_send_supported_modes_signal(mode_list);
g_free(mode_list);
}
Expand All @@ -216,7 +216,7 @@ void common_send_available_modes_signal(void)
{
LOG_REGISTER_CONTEXT;

gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST);
gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST, 0);
umdbus_send_available_modes_signal(mode_list);
g_free(mode_list);
}
Expand Down Expand Up @@ -503,10 +503,12 @@ int common_valid_mode(const char *mode)
/** make a list of all available usb modes
*
* @param type The type of list to return. Supported or available.
* @param uid Uid of the process requesting the information;
* this is used to limit allowed modes, 0 returns all
*
* @return a comma-separated list of modes (MODE_ASK not included as it is not a real mode)
*/
gchar *common_get_mode_list(mode_list_type_t type)
gchar *common_get_mode_list(mode_list_type_t type, uid_t uid)
{
LOG_REGISTER_CONTEXT;

Expand Down Expand Up @@ -544,6 +546,10 @@ gchar *common_get_mode_list(mode_list_type_t type)
{
modedata_t *data = iter->data;

/* skip dynamic modes that are not allowed */
if (!usbmoded_is_mode_permitted(data->mode_name, uid))
continue;

/* skip items in the hidden list */
if (common_mode_in_list(data->mode_name, hidden_modes_array))
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/usb_moded-common.h
Expand Up @@ -61,7 +61,7 @@ waitres_t common_wait (unsigned tot_ms, bool (*ready_c
bool common_msleep_ (const char *file, int line, const char *func, unsigned msec);
bool common_modename_is_internal (const char *modename);
int common_valid_mode (const char *mode);
gchar *common_get_mode_list (mode_list_type_t type);
gchar *common_get_mode_list (mode_list_type_t type, uid_t uid);

/* ========================================================================= *
* Macros
Expand Down
31 changes: 26 additions & 5 deletions src/usb_moded-control.c
Expand Up @@ -58,6 +58,7 @@ void control_set_cable_state (cable_state_t cable_state);
cable_state_t control_get_cable_state (void);
void control_clear_cable_state (void);
bool control_get_connection_state (void);
void control_set_last_seen_user (uid_t uid);

/* ========================================================================= *
* Data
Expand Down Expand Up @@ -89,6 +90,12 @@ static char *control_internal_mode = NULL;
*/
static cable_state_t control_cable_state = CABLE_STATE_UNKNOWN;

/** Last user seen
*
* Defaults to invalid user which has no rights.
*/
static uid_t control_last_seen_user = (uid_t)-1;

/* ========================================================================= *
* Functions
* ========================================================================= */
Expand Down Expand Up @@ -337,12 +344,17 @@ void control_select_usb_mode(void)
/* If there is only one allowed mode, use it without
* going through ask-mode */
if( !strcmp(MODE_ASK, mode_to_set) ) {
// FIXME free() vs g_free() conflict
gchar *available = common_get_mode_list(AVAILABLE_MODES_LIST);
if( *available && !strchr(available, ',') ) {
free(mode_to_set), mode_to_set = available, available = 0;
if( control_last_seen_user == (uid_t)-1 ) {
/* Use charging only if no user has been seen */
free(mode_to_set), mode_to_set = 0;
} else {
// FIXME free() vs g_free() conflict
gchar *available = common_get_mode_list(AVAILABLE_MODES_LIST, control_last_seen_user);
if( *available && !strchr(available, ',') ) {
free(mode_to_set), mode_to_set = available, available = 0;
}
g_free(available);
}
g_free(available);
}

if( mode_to_set && usbmoded_can_export() ) {
Expand Down Expand Up @@ -431,3 +443,12 @@ bool control_get_connection_state(void)
}
return connected;
}

/** Set the last seen user
*
* @param uid of last seen user, controls implicitly set modes
*/
void control_set_last_seen_user(uid_t uid)
{
control_last_seen_user = uid;
}
1 change: 1 addition & 0 deletions src/usb_moded-control.h
Expand Up @@ -49,5 +49,6 @@ void control_set_cable_state (cable_state_t cable_state);
cable_state_t control_get_cable_state (void);
void control_clear_cable_state (void);
bool control_get_connection_state (void);
void control_set_last_seen_user (uid_t uid);

#endif /* USB_MODED_CONTROL_H_ */
3 changes: 3 additions & 0 deletions src/usb_moded-dbus-private.h
Expand Up @@ -42,6 +42,9 @@
/** Logical name for org.freedesktop.DBus.NameOwnerChanged signal */
# define DBUS_NAME_OWNER_CHANGED_SIG "NameOwnerChanged"

/** Logical name for org.freedesktop.DBus.GetNameOwner method */
# define DBUS_GET_CONNECTION_PID_REQ "GetConnectionUnixProcessID"

/* ========================================================================= *
* Types
* ========================================================================= */
Expand Down
105 changes: 103 additions & 2 deletions src/usb_moded-dbus.c
Expand Up @@ -40,6 +40,7 @@

#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include <dbus/dbus-glib-lowlevel.h>

Expand Down Expand Up @@ -84,6 +85,7 @@ int umdbus_send_hidden_modes_signal (const char *hidde
int umdbus_send_whitelisted_modes_signal(const char *whitelist);
static void umdbus_get_name_owner_cb (DBusPendingCall *pc, void *aptr);
gboolean umdbus_get_name_owner_async (const char *name, usb_moded_get_name_owner_fn cb, DBusPendingCall **ppc);
uid_t umdbus_get_sender_uid (const char *sender);

/* ========================================================================= *
* Data
Expand Down Expand Up @@ -161,6 +163,9 @@ static const char umdbus_introspect_usbmoded[] =
" <method name=\"" USB_MODE_AVAILABLE_MODES_GET "\">\n"
" <arg name=\"modes\" type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"" USB_MODE_AVAILABLE_MODES_FOR_USER "\">\n"
" <arg name=\"modes\" type=\"s\" direction=\"out\"/>\n"
" </method>\n"
" <method name=\"" USB_MODE_HIDE "\">\n"
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"
" <arg name=\"mode\" type=\"s\" direction=\"out\"/>\n"
Expand Down Expand Up @@ -284,6 +289,7 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
const char *member = dbus_message_get_member(msg);
const char *object = dbus_message_get_path(msg);
int type = dbus_message_get_type(msg);
const char *sender = dbus_message_get_sender(msg);

(void)user_data;

Expand Down Expand Up @@ -340,11 +346,17 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
const char *mode = control_get_external_mode();
char *use = 0;
DBusError err = DBUS_ERROR_INIT;
uid_t uid = umdbus_get_sender_uid(sender);

if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID)) {
log_err("parse error: %s: %s", err.name, err.message);
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
}
else if( !usbmoded_is_mode_permitted(use, uid) ) {
/* Insufficient permissions */
log_warning("Mode '%s' is not allowed for uid %d", use, uid);
reply = dbus_message_new_error(msg, DBUS_ERROR_ACCESS_DENIED, member);
}
else if( control_get_cable_state() != CABLE_STATE_PC_CONNECTED ) {
/* Mode change makes no sence unless we have a PC connection */
log_warning("Mode '%s' requested while not connected to pc", use);
Expand Down Expand Up @@ -401,6 +413,11 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB

if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID))
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
#ifdef SAILFISH_ACCESS_CONTROL
/* do not let non-owner user hide modes */
else if (!sailfish_access_control_hasgroup(umdbus_get_sender_uid(sender), "sailfish-system"))
reply = dbus_message_new_error(msg, DBUS_ERROR_ACCESS_DENIED, member);
#endif
else
{
/* error checking is done when setting configuration */
Expand All @@ -422,6 +439,11 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB

if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID))
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
#ifdef SAILFISH_ACCESS_CONTROL
/* do not let non-owner user unhide modes */
else if (!sailfish_access_control_hasgroup(umdbus_get_sender_uid(sender), "sailfish-system"))
reply = dbus_message_new_error(msg, DBUS_ERROR_ACCESS_DENIED, member);
#endif
else
{
/* error checking is done when setting configuration */
Expand Down Expand Up @@ -500,20 +522,31 @@ static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DB
}
else if(!strcmp(member, USB_MODE_LIST))
{
gchar *mode_list = common_get_mode_list(SUPPORTED_MODES_LIST);
gchar *mode_list = common_get_mode_list(SUPPORTED_MODES_LIST, 0);

if((reply = dbus_message_new_method_return(msg)))
dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID);
g_free(mode_list);
}
else if(!strcmp(member, USB_MODE_AVAILABLE_MODES_GET))
{
gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST);
gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST, 0);

if((reply = dbus_message_new_method_return(msg)))
dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID);
g_free(mode_list);
}
else if(!strcmp(member, USB_MODE_AVAILABLE_MODES_FOR_USER))
{
uid_t uid = umdbus_get_sender_uid(sender);
gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST, uid);

if((reply = dbus_message_new_method_return(msg)))
dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID);
g_free(mode_list);

control_set_last_seen_user(uid);
}
else if(!strcmp(member, USB_MODE_RESCUE_OFF))
{
usbmoded_set_rescue_mode(false);
Expand Down Expand Up @@ -1323,3 +1356,71 @@ gboolean umdbus_get_name_owner_async(const char *name,

return ack;
}

/**
* Get uid of sender from D-Bus. This makes a synchronous D-Bus call
*
* @param name Name of sender from DBusMessage
* @return Uid of the sender
*/
uid_t umdbus_get_sender_uid(const char *name)
{
LOG_REGISTER_CONTEXT;

pid_t pid = (pid_t)-1;
uid_t uid = (uid_t)-1;
DBusMessage *req = 0;
DBusMessage *rsp = 0;
DBusError err = DBUS_ERROR_INIT;
char path[256];
struct stat st;

if(!umdbus_connection)
goto EXIT;

req = dbus_message_new_method_call(DBUS_INTERFACE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
DBUS_GET_CONNECTION_PID_REQ);
if( !req ) {
log_err("could not create method call message");
goto EXIT;
}

if( !dbus_message_append_args(req,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID) ) {
log_err("could not add method call parameters");
goto EXIT;
}

/* Synchronous D-Bus call */
rsp = dbus_connection_send_with_reply_and_block(umdbus_connection, req, -1, &err);

if( !rsp && dbus_error_is_set(&err) ) {
log_err("could not get sender pid for %s: %s: %s", name, err.name, err.message);
goto EXIT;
}

if( !dbus_message_get_args(rsp, &err,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID) ) {
log_err("parse error: %s: %s", err.name, err.message);
goto EXIT;
}

snprintf(path, sizeof path, "/proc/%d", (int)pid);
memset(&st, 0, sizeof st);
if( stat(path, &st) != -1 ) {
uid = st.st_uid;
}

EXIT:

if( req ) dbus_message_unref(req);
if( rsp ) dbus_message_unref(rsp);

dbus_error_free(&err);

return uid;
}

0 comments on commit e692ad5

Please sign in to comment.