From: Jiyong Date: Wed, 17 Apr 2024 23:47:42 +0000 (+0900) Subject: Modify to limit the size of message for socket ipc X-Git-Tag: accepted/tizen/unified/20240424.063525^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F86%2F309886%2F9;p=platform%2Fcore%2Fapi%2Fmedia-controller.git Modify to limit the size of message for socket ipc [Problem] DoS is available by calling g_malloc0 with too big msg_size value. [Solution] The size of messages with socket has been limited to 10kbytes and large messages will be sent as file. Change-Id: Ie2cf9f4f3a3ec111fcf220724427f29b5157729a --- diff --git a/include/media_controller_private.h b/include/media_controller_private.h index a9c0278..a925a4c 100644 --- a/include/media_controller_private.h +++ b/include/media_controller_private.h @@ -409,6 +409,7 @@ gboolean _mc_util_is_valid_subscription_type(const mc_subscription_type_e subscr void _mc_util_set_bit(int bit_num, gboolean set, unsigned long long *value); gboolean _mc_util_is_true_bit(unsigned long long value, int bit_num); const char * _mc_util_replace_null(const char *data); +gchar *_mc_util_write_message_to_file(const gchar *data, gssize size); /* for d-bus IPC */ int _mc_ipc_get_dbus_connection(GDBusConnection **conn, int *dref_count); diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec index 2df010e..279322b 100644 --- a/packaging/capi-media-controller.spec +++ b/packaging/capi-media-controller.spec @@ -1,6 +1,6 @@ Name: capi-media-controller Summary: A media controller library in Tizen Native API -Version: 0.2.46 +Version: 0.2.47 Release: 1 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_controller_db.c b/src/media_controller_db.c index c77a5e2..ddf7f23 100644 --- a/src/media_controller_db.c +++ b/src/media_controller_db.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "media_controller_private.h" #include "media_controller_db.h" @@ -149,10 +150,12 @@ int _mc_db_update_whole_metadata(const char *server_name, { int ret = MEDIA_CONTROLLER_ERROR_NONE; char *sql_str = NULL; + gchar *message = NULL; + gchar *message_file = NULL; mc_retvm_if(!server_name, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name"); - sql_str = g_strdup_printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", MC_DB_CMD_UPDATE_META, MC_STRING_DELIMITER, server_name, MC_STRING_DELIMITER, + message = g_strdup_printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", server_name, MC_STRING_DELIMITER, title, MC_STRING_DELIMITER, artist, MC_STRING_DELIMITER, album, MC_STRING_DELIMITER, @@ -168,8 +171,20 @@ int _mc_db_update_whole_metadata(const char *server_name, episode, MC_STRING_DELIMITER, resolution); + mc_retvm_if(!message, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "message is NULL"); + + message_file = _mc_util_write_message_to_file(message, strlen(message)); + g_free(message); + mc_retvm_if(!message_file, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "message_file is NULL"); + + sql_str = g_strdup_printf("%s%s%s", MC_DB_CMD_UPDATE_META, MC_STRING_DELIMITER, message_file); + ret = __mc_db_update_db(MC_PRIV_TYPE_SERVER, sql_str); + if (g_remove(message_file) != 0) + mc_secure_debug("Temporary message_file has not been removed [%s]", message_file); + + g_free(message_file); g_free(sql_str); return ret; @@ -925,16 +940,24 @@ int _mc_db_update_playlist(const char *server_name, const char *playlist_name, b { int ret = MEDIA_CONTROLLER_ERROR_NONE; char *sql_str = NULL; + gchar *message_file = NULL; mc_retvm_if(!server_name, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL"); mc_retvm_if(!playlist_name, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "playlist_name is NULL"); mc_retvm_if(!bundle_data, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "bundle_data is NULL"); - sql_str = g_strdup_printf("%s%s%s%s%s%s%d%s%s", MC_DB_CMD_UPDATE_PLAYLIST, MC_STRING_DELIMITER, server_name, - MC_STRING_DELIMITER, playlist_name, MC_STRING_DELIMITER, bundle_size, MC_STRING_DELIMITER, bundle_data); + message_file = _mc_util_write_message_to_file((gchar *)bundle_data, bundle_size); + mc_retvm_if(!message_file, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "message_file is NULL"); + + sql_str = g_strdup_printf("%s%s%s%s%s%s%s", MC_DB_CMD_UPDATE_PLAYLIST, MC_STRING_DELIMITER, server_name, + MC_STRING_DELIMITER, playlist_name, MC_STRING_DELIMITER, message_file); ret = __mc_db_update_db(MC_PRIV_TYPE_SERVER, sql_str); + if (g_remove(message_file) != 0) + mc_secure_debug("Temporary message_file has not been removed [%s]", message_file); + + g_free(message_file); g_free(sql_str); return ret; diff --git a/src/media_controller_ipc.c b/src/media_controller_ipc.c index 94acfa3..c27f314 100644 --- a/src/media_controller_ipc.c +++ b/src/media_controller_ipc.c @@ -333,25 +333,26 @@ static int __make_service_connection(mc_priv_type_e priv_type) int _mc_ipc_send_message_to_server(mc_msg_type_e msg_type, mc_priv_type_e priv_type, const char *request_msg) { int ret = MEDIA_CONTROLLER_ERROR_NONE; - int request_msg_size = 0; int sockfd = -1; struct sockaddr_un serv_addr; + mc_comm_msg_s send_msg; + int recv_msg = -1; unsigned int retry_count = 0; - mc_retvm_if(!MC_STRING_VALID(request_msg), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid query"); - - request_msg_size = strlen(request_msg); + mc_retvm_if(!MC_STRING_VALID(request_msg), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, + "invalid request_msg"); mc_secure_debug("msg_type[%d] priv_type[%d], message[%s]", msg_type, priv_type, request_msg); - mc_comm_msg_s send_msg; memset((void *)&send_msg, 0, sizeof(mc_comm_msg_s)); send_msg.msg_type = msg_type; send_msg.priv_type = priv_type; send_msg.pid = getpid(); send_msg.uid = getuid(); - send_msg.msg_size = request_msg_size; + send_msg.msg_size = g_strlcpy(send_msg.msg, request_msg, MAX_MSG_SIZE); + mc_retvm_if(send_msg.msg_size >= MAX_MSG_SIZE, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, + "invalid request_msg size(%zu)", send_msg.msg_size); /* Create Socket */ ret = mc_ipc_create_client_socket(MC_TIMEOUT_SEC_5, &sockfd); @@ -369,62 +370,25 @@ int _mc_ipc_send_message_to_server(mc_msg_type_e msg_type, mc_priv_type_e priv_t return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; } - size_t full_msg_size = 0; - size_t head_msg_size = 0; - size_t send_msg_size = 0; - size_t temp_buf_index = 0; - char *temp_buf = NULL; - - head_msg_size = sizeof(send_msg) - sizeof(send_msg.msg); - full_msg_size = head_msg_size + request_msg_size; - - temp_buf = g_malloc0(full_msg_size + 1); - - memcpy(temp_buf, &send_msg, head_msg_size); - memcpy(temp_buf + head_msg_size, request_msg, request_msg_size); - - if (full_msg_size <= MAX_MSG_SIZE) - send_msg_size = full_msg_size; - else - send_msg_size = head_msg_size; - - while (temp_buf_index < full_msg_size) { - size_t send_result = 0; - /* Send request */ - send_result = send(sockfd, temp_buf + temp_buf_index, send_msg_size, 0); - if (send_result < send_msg_size) { - mc_stderror("send failed"); - close(sockfd); - g_free(temp_buf); - return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; - } - temp_buf_index += send_result; - if ((full_msg_size - temp_buf_index) > MAX_MSG_SIZE) - send_msg_size = MAX_MSG_SIZE; - else - send_msg_size = full_msg_size - temp_buf_index; + if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) { + mc_stderror("send failed"); + close(sockfd); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; } - g_free(temp_buf); + mc_debug("SEND MESSAGE OK"); /* Receive Response */ - int recv_msg_size = -1; - int recv_msg = -1; - - while ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) { - + while (recv(sockfd, &recv_msg, sizeof(recv_msg), 0) < 0) { if (errno == EINTR) { mc_stderror("catch interrupt"); continue; - } else if (errno == EWOULDBLOCK) { if (retry_count++ < MAX_RETRY_COUNT) { mc_error("[No-Error] Time Out. retry_count [%d]", retry_count); continue; } - mc_error("Timeout. Can't try any more"); - } else { mc_stderror("recv failed"); } @@ -434,10 +398,9 @@ int _mc_ipc_send_message_to_server(mc_msg_type_e msg_type, mc_priv_type_e priv_t } mc_debug("RECEIVE OK [%d]", recv_msg); - ret = recv_msg; close(sockfd); - return ret; + return recv_msg; } #ifdef _ON_DEMAND_SOCKET_ACTIVATION diff --git a/src/media_controller_util.c b/src/media_controller_util.c index a651be2..f3cd2f7 100644 --- a/src/media_controller_util.c +++ b/src/media_controller_util.c @@ -299,3 +299,48 @@ const char * _mc_util_replace_null(const char *data) else return data; } + +static gchar *_mc_util_make_message_file(void) +{ + int fd = 0; + gchar *path = NULL; + const char *template = "XXXXXX.mc"; + GError *error = NULL; + + fd = g_file_open_tmp(template, &path, &error); + if (fd < 0) { + mc_secure_error("g_file_open_tmp error [%s]", (error ? error->message : "none")); + g_error_free(error); + return NULL; + } + + mc_secure_debug("make temp file [%s]", path); + + close(fd); + + return path; +} + +gchar *_mc_util_write_message_to_file(const gchar *data, gssize size) +{ + gchar *path = _mc_util_make_message_file(); + GError *error = NULL; + + mc_retvm_if(!MC_STRING_VALID(path), NULL, "invalid path %s", path); + mc_retvm_if(!data, NULL, "data is null"); + mc_retvm_if(size == 0, NULL, "size is 0"); + + mc_debug_fenter(); + + if (!g_file_set_contents(path, data, size, &error)) { + mc_secure_error("g_file_set_contents error(%s: %s)", path, (error ? error->message : "none")); + if (error) + g_error_free(error); + g_free(path); + return NULL; + } + + mc_debug_fleave(); + + return path; +} diff --git a/svc/include/media_controller_socket.h b/svc/include/media_controller_socket.h index d9f4f00..d7db351 100755 --- a/svc/include/media_controller_socket.h +++ b/svc/include/media_controller_socket.h @@ -53,7 +53,7 @@ typedef struct { uid_t uid; int result; size_t msg_size; - char *msg; + char msg[MAX_MSG_SIZE]; } mc_comm_msg_s; int mc_ipc_create_client_socket(int timeout_sec, int *sock_fd); diff --git a/svc/media_controller_cynara.c b/svc/media_controller_cynara.c index b0d7028..2465f51 100755 --- a/svc/media_controller_cynara.c +++ b/svc/media_controller_cynara.c @@ -68,14 +68,11 @@ void mc_cynara_finish(void) int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_peer_creds *credentials) { int ret = 0; - size_t recv_msg_size = 0; - size_t head_size = 0; if (!recv_msg || !credentials) return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; - head_size = sizeof(mc_comm_msg_s) - sizeof(recv_msg->msg); - if ((recv_msg_size = read(sockfd, recv_msg, head_size)) < head_size) { + if (read(sockfd, recv_msg, sizeof(mc_comm_msg_s)) != sizeof(mc_comm_msg_s)) { if (errno == EWOULDBLOCK) { mc_error("Timeout. Can't try any more"); return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; @@ -85,52 +82,6 @@ int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_ } } - if ((recv_msg->msg_size > 0) && (recv_msg->msg_size <= SIZE_MAX - 1)) { - size_t remain_size = recv_msg->msg_size; - size_t block_size = 0; - size_t msg_index = 0; - char *recv_buf = NULL; - - recv_buf = g_malloc0(MAX_MSG_SIZE + 1); - recv_msg->msg = g_malloc0(recv_msg->msg_size + 1); - - while (remain_size > 0) { - memset(recv_buf, 0, MAX_MSG_SIZE + 1); - if (remain_size < MAX_MSG_SIZE) - block_size = remain_size; - else - block_size = MAX_MSG_SIZE; - - if ((recv_msg_size = read(sockfd, recv_buf, block_size)) < block_size) { - g_free(recv_buf); - g_free(recv_msg->msg); - if (errno == EWOULDBLOCK) { - mc_error("Timeout. Can't try any more"); - return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; - } else { - mc_stderror("recv failed"); - return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; - } - } - - if (recv_msg_size > remain_size) { - mc_error("recv_msg_size [%zu] remain_size [%zu]", recv_msg_size, remain_size); - break; - } - - memcpy(recv_msg->msg + msg_index, recv_buf, recv_msg_size); - msg_index += recv_msg_size; - - remain_size -= recv_msg_size; - } - - g_free(recv_buf); - } else { - mc_error("wrong msg_size [%zu]", recv_msg->msg_size); - recv_msg->msg = NULL; - return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; - } - /* mc_debug("receive msg[%d] from [%d(%d)] %d, %s", recv_msg_size, recv_msg->pid, recv_msg->uid, recv_msg->msg_type, recv_msg->msg); */ ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid)); diff --git a/svc/media_controller_db_util.c b/svc/media_controller_db_util.c index 4985224..188d816 100644 --- a/svc/media_controller_db_util.c +++ b/svc/media_controller_db_util.c @@ -640,6 +640,31 @@ static void __sqlite3_safe_free(gpointer data) SQLITE3_SAFE_FREE(data); } +int __read_message_from_file(const gchar *path, gchar **data, size_t *size) +{ + GError *error = NULL; + gsize read_n = 0; + + mc_retvm_if(!MC_STRING_VALID(path), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "invalid path %s", path); + mc_retvm_if(!data, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "data is null"); + mc_retvm_if(!size, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "size is null"); + + mc_debug_fenter(); + + if (!g_file_get_contents(path, data, &read_n, &error)) { + mc_secure_error("g_file_get_contents error(%s: %s)", path, (error ? error->message : "none")); + if (error) + g_error_free(error); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + *size = read_n; + + mc_debug_fleave(); + + return MEDIA_CONTROLLER_ERROR_NONE; +} + static int __parse_db_request(gchar **params, char **sql_str) { int ret = MEDIA_CONTROLLER_ERROR_NONE; @@ -675,13 +700,26 @@ static int __parse_db_request(gchar **params, char **sql_str) } } else if (strncmp(MC_DB_CMD_UPDATE_META, params[0], strlen(MC_DB_CMD_UPDATE_META)) == 0) { - _sql_str = sqlite3_mprintf("INSERT OR REPLACE INTO %q VALUES (%Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q)", - MC_DB_TABLE_LATEST_META, params[1], - __replace_null(params[2]), __replace_null(params[3]), __replace_null(params[4]), __replace_null(params[5]), - __replace_null(params[6]), __replace_null(params[7]), __replace_null(params[8]), __replace_null(params[9]), - __replace_null(params[10]), __replace_null(params[11]), __replace_null(params[12]), __replace_null(params[13]), - __replace_null(params[14]), __replace_null(params[15])); + gchar *message = NULL; + size_t message_size = 0; + gchar **meta_params = NULL; + mc_retvm_if((__read_message_from_file(params[1], &message, &message_size) != MEDIA_CONTROLLER_ERROR_NONE), + MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__read_message_from_file failed"); + + meta_params = g_strsplit(message, MC_STRING_DELIMITER, 0); + g_free(message); + mc_retvm_if(!meta_params, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail to parsing message"); + + _sql_str = sqlite3_mprintf("INSERT OR REPLACE INTO %q VALUES (%Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q)", + MC_DB_TABLE_LATEST_META, meta_params[0], + __replace_null(meta_params[1]), __replace_null(meta_params[2]), __replace_null(meta_params[3]), + __replace_null(meta_params[4]), __replace_null(meta_params[5]), __replace_null(meta_params[6]), + __replace_null(meta_params[7]), __replace_null(meta_params[8]), __replace_null(meta_params[9]), + __replace_null(meta_params[10]), __replace_null(meta_params[11]), __replace_null(meta_params[12]), + __replace_null(meta_params[13]), __replace_null(meta_params[14])); + + g_strfreev(meta_params); } else if (strncmp(MC_DB_CMD_UPDATE_SHUFFLE, params[0], strlen(MC_DB_CMD_UPDATE_SHUFFLE)) == 0) { mc_retvm_if(!params[2], MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "invalid query"); @@ -704,15 +742,19 @@ static int __parse_db_request(gchar **params, char **sql_str) _sql_str = sqlite3_mprintf("INSERT INTO %q(server_name, playlist_name) VALUES (%Q, %Q)", MC_DB_TABLE_PLAYLIST, params[1], params[2]); } else if (strncmp(MC_DB_CMD_UPDATE_PLAYLIST, params[0], strlen(MC_DB_CMD_UPDATE_PLAYLIST)) == 0) { + gchar *message = NULL; + size_t message_size = 0; bundle *bundle = NULL; playlist_query_s playlist_query = { NULL, NULL, NULL, 0 }; GSList *iter = NULL; - mc_retvm_if((!params[2] || !params[3] || !params[4]), + mc_retvm_if((!params[2] || !params[3]), MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "invalid query"); + mc_retvm_if((__read_message_from_file(params[3], &message, &message_size) != MEDIA_CONTROLLER_ERROR_NONE), + MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__read_message_from_file failed"); - mc_safe_strtoi(params[3], &i_value); - bundle = bundle_decode((bundle_raw *)params[4], i_value); + bundle = bundle_decode((bundle_raw *)message, (int)message_size); + g_free(message); mc_retvm_if(!bundle, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "invalid bundle_data"); mc_debug("bundle item count [%d]", bundle_get_count(bundle)); diff --git a/svc/media_controller_svc.c b/svc/media_controller_svc.c index bdce471..3d0047f 100644 --- a/svc/media_controller_svc.c +++ b/svc/media_controller_svc.c @@ -94,8 +94,6 @@ static void __mc_destroy_queue(gpointer data) mc_service_request *req = (mc_service_request *)data; mc_retm_if_failed(req); - if (req->req_msg) - g_free(req->req_msg->msg); g_free(req->req_msg); g_free(req); }