From 1d40c0cc1b3511e9dfa4f8d2f599804505709be0 Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Sun, 10 Feb 2019 11:48:41 +0000 Subject: [PATCH] Refactor to use single internal functions for register, unregister and query --- daemon/dbus_messaging.c | 16 ++-- daemon/gamemode.c | 179 ++++++++++++++++------------------------ daemon/gamemode.h | 50 +++-------- 3 files changed, 92 insertions(+), 153 deletions(-) diff --git a/daemon/dbus_messaging.c b/daemon/dbus_messaging.c index c74435e..40da5d6 100644 --- a/daemon/dbus_messaging.c +++ b/daemon/dbus_messaging.c @@ -75,9 +75,9 @@ static int method_register_game(sd_bus_message *m, void *userdata, return ret; } - game_mode_context_register(context, (pid_t)pid); + int status = game_mode_context_register(context, (pid_t)pid, (pid_t)pid); - return sd_bus_reply_method_return(m, "i", 0); + return sd_bus_reply_method_return(m, "i", status); } /** @@ -95,9 +95,9 @@ static int method_unregister_game(sd_bus_message *m, void *userdata, return ret; } - game_mode_context_unregister(context, (pid_t)pid); + int status = game_mode_context_unregister(context, (pid_t)pid, (pid_t)pid); - return sd_bus_reply_method_return(m, "i", 0); + return sd_bus_reply_method_return(m, "i", status); } /** @@ -115,7 +115,7 @@ static int method_query_status(sd_bus_message *m, void *userdata, return ret; } - int status = game_mode_context_query_status(context, (pid_t)pid); + int status = game_mode_context_query_status(context, (pid_t)pid, (pid_t)pid); return sd_bus_reply_method_return(m, "i", status); } @@ -136,7 +136,7 @@ static int method_register_game_by_pid(sd_bus_message *m, void *userdata, return ret; } - int reply = game_mode_context_register_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); + int reply = game_mode_context_register(context, (pid_t)gamepid, (pid_t)callerpid); return sd_bus_reply_method_return(m, "i", reply); } @@ -157,7 +157,7 @@ static int method_unregister_game_by_pid(sd_bus_message *m, void *userdata, return ret; } - int reply = game_mode_context_unregister_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); + int reply = game_mode_context_unregister(context, (pid_t)gamepid, (pid_t)callerpid); return sd_bus_reply_method_return(m, "i", reply); } @@ -178,7 +178,7 @@ static int method_query_status_by_pid(sd_bus_message *m, void *userdata, return ret; } - int status = game_mode_context_query_status_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); + int status = game_mode_context_query_status(context, (pid_t)gamepid, (pid_t)callerpid); return sd_bus_reply_method_return(m, "i", status); } diff --git a/daemon/gamemode.c b/daemon/gamemode.c index ea1de89..5d35bed 100644 --- a/daemon/gamemode.c +++ b/daemon/gamemode.c @@ -291,7 +291,7 @@ static void game_mode_context_auto_expire(GameModeContext *self) if (kill(client->pid, 0) != 0) { LOG_MSG("Removing expired game [%i]...\n", client->pid); pthread_rwlock_unlock(&self->rwlock); - game_mode_context_unregister(self, client->pid); + game_mode_context_unregister(self, client->pid, client->pid); removing = true; break; } @@ -335,20 +335,40 @@ static int game_mode_context_num_clients(GameModeContext *self) return atomic_load(&self->refcount); } -bool game_mode_context_register(GameModeContext *self, pid_t client) +int game_mode_context_register(GameModeContext *self, pid_t client, pid_t requester) { + errno = 0; + /* Construct a new client if we can */ GameModeClient *cl = NULL; char *executable = NULL; + /* Check our requester config first */ + if (requester != client) { + /* Lookup the executable first */ + executable = game_mode_context_find_exe(requester); + if (!executable) { + return -1; + } + + /* Check our blacklist and whitelist */ + if (!config_get_supervisor_whitelisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); + free(executable); + return -2; + } else if (config_get_supervisor_blacklisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); + free(executable); + return -2; + } + } + /* Cap the total number of active clients */ if (game_mode_context_num_clients(self) + 1 > MAX_GAMES) { LOG_ERROR("Max games (%d) reached, not registering %d\n", MAX_GAMES, client); - return false; + goto error_cleanup; } - errno = 0; - /* Check the PID first to spare a potentially expensive lookup for the exe */ pthread_rwlock_rdlock(&self->rwlock); // ensure our pointer is sane const GameModeClient *existing = game_mode_context_has_client(self, client); @@ -414,15 +434,37 @@ error_cleanup: LOG_ERROR("Failed to register client [%d]: %s\n", client, strerror(errno)); free(executable); game_mode_client_free(cl); - return false; + return -1; } -bool game_mode_context_unregister(GameModeContext *self, pid_t client) +int game_mode_context_unregister(GameModeContext *self, pid_t client, pid_t requester) { GameModeClient *cl = NULL; GameModeClient *prev = NULL; bool found = false; + /* Check our requester config first */ + if (requester != client) { + /* Lookup the executable first */ + char *executable = game_mode_context_find_exe(requester); + if (!executable) { + return -1; + } + + /* Check our blacklist and whitelist */ + if (!config_get_supervisor_whitelisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); + free(executable); + return -2; + } else if (config_get_supervisor_blacklisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); + free(executable); + return -2; + } + + free(executable); + } + /* Requires locking. */ pthread_rwlock_wrlock(&self->rwlock); @@ -457,7 +499,7 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t client) " -- with a nearby 'Removing expired game' which means we cleaned up properly\n" " -- (we will log this event). This hint will be displayed only once.\n", client); - return false; + return -1; } /* When we hit bottom then end the game mode */ @@ -468,11 +510,32 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t client) return true; } -int game_mode_context_query_status(GameModeContext *self, pid_t client) +int game_mode_context_query_status(GameModeContext *self, pid_t client, pid_t requester) { GameModeClient *cl = NULL; int ret = 0; + /* First check the requester settings if appropriate */ + if (client != requester) { + char *executable = game_mode_context_find_exe(requester); + if (!executable) { + return -1; + } + + /* Check our blacklist and whitelist */ + if (!config_get_supervisor_whitelisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); + free(executable); + return -2; + } else if (config_get_supervisor_blacklisted(self->config, executable)) { + LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); + free(executable); + return -2; + } + + free(executable); + } + /* * Check the current refcount on gamemode, this equates to whether gamemode is active or not, * see game_mode_context_register and game_mode_context_unregister @@ -502,104 +565,6 @@ int game_mode_context_query_status(GameModeContext *self, pid_t client) return ret; } -/** - * Register on behalf of caller - * TODO: long config_get_require_supervisor(GameModeConfig *self); - */ -int game_mode_context_register_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid) -{ - int status = 0; - - /* Lookup the executable first */ - char *executable = game_mode_context_find_exe(callerpid); - if (!executable) { - status = -1; - goto error_cleanup; - } - - /* Check our blacklist and whitelist */ - if (!config_get_supervisor_whitelisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); - status = -2; - goto error_cleanup; - } else if (config_get_supervisor_blacklisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); - status = -2; - goto error_cleanup; - } - - /* Checks cleared, try and register the game */ - return game_mode_context_register(self, gamepid); - -error_cleanup: - free(executable); - return status; -} - -/** - * Unregister on behalf of caller - */ -int game_mode_context_unregister_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid) -{ - int status = 0; - - /* Lookup the executable first */ - char *executable = game_mode_context_find_exe(callerpid); - if (!executable) { - status = -1; - goto error_cleanup; - } - - /* Check our blacklist and whitelist */ - if (!config_get_supervisor_whitelisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); - status = -2; - goto error_cleanup; - } else if (config_get_supervisor_blacklisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); - status = -2; - goto error_cleanup; - } - /* Checks cleared, try and register the game */ - return game_mode_context_unregister(self, gamepid); - -error_cleanup: - free(executable); - return status; -} - -/** - * Request status on behalf of caller - */ -int game_mode_context_query_status_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid) -{ - int status = 0; - - /* Lookup the executable first */ - char *executable = game_mode_context_find_exe(callerpid); - if (!executable) { - status = -1; - goto error_cleanup; - } - - /* Check our blacklist and whitelist */ - if (!config_get_supervisor_whitelisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable); - status = -2; - goto error_cleanup; - } else if (config_get_supervisor_blacklisted(self->config, executable)) { - LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable); - status = -2; - goto error_cleanup; - } - /* Checks cleared, call the original query */ - return game_mode_context_query_status(self, gamepid); - -error_cleanup: - free(executable); - return status; -} - /** * Construct a new GameModeClient for the given process ID * diff --git a/daemon/gamemode.h b/daemon/gamemode.h index dca0652..9a30e52 100644 --- a/daemon/gamemode.h +++ b/daemon/gamemode.h @@ -67,17 +67,23 @@ void game_mode_context_destroy(GameModeContext *self); * Register a new game client with the context * * @param pid Process ID for the remote client - * @returns True if the new client could be registered + * @param requester Process ID for the remote requestor + * @returns 0 if the request was accepted and the client could be registered + * -1 if the request was accepted but the client could not be registered + * -2 if the request was rejected */ -bool game_mode_context_register(GameModeContext *self, pid_t pid); +int game_mode_context_register(GameModeContext *self, pid_t pid, pid_t requester); /** * Unregister an existing remote game client from the context * * @param pid Process ID for the remote client - * @returns True if the client was removed, and existed. + * @param requester Process ID for the remote requestor + * @returns 0 if the request was accepted and the client existed + * -1 if the request was accepted but the client did not exist + * -2 if the request was rejected */ -bool game_mode_context_unregister(GameModeContext *self, pid_t pid); +int game_mode_context_unregister(GameModeContext *self, pid_t pid, pid_t requester); /** * Query the current status of gamemode @@ -86,41 +92,9 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t pid); * @returns Positive if gamemode is active * 1 if gamemode is active but the client is not registered * 2 if gamemode is active and the client is registered + * -2 if this requester was rejected */ -int game_mode_context_query_status(GameModeContext *self, pid_t pid); - -/** - * Register a new game client with the context on behalf of another process - * - * @param callerpid Process ID for the remote client making the request - * @param gamepid Process ID for the process to be registered - * @returns 0 if the request was accepted and the client could be registered - * -1 if the request was accepted but the client could not be registered - * -2 if the request was rejected - */ -int game_mode_context_register_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid); - -/** - * Unregister an existing remote game client from the context on behalf of another process - * - * @param callerpid Process ID for the remote client making the request - * @param gamepid Process ID for the process to be registered - * @returns 0 if the request was accepted and the client existed - * -1 if the request was accepted but the client did not exist - * -2 if the request was rejected - */ -int game_mode_context_unregister_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid); - -/** - * Query the current status of gamemode for another process - * - * @param pid Process ID for the remote client - * @returns Positive if gamemode is active - * 1 if gamemode is active but the client is not registered - * 2 if gamemode is active and the client is registered - * -2 if this supervisor was rejected - */ -int game_mode_context_query_status_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid); +int game_mode_context_query_status(GameModeContext *self, pid_t pid, pid_t requester); /** * Query the config of a gamemode context