From: Sung-hun Kim Date: Fri, 2 Sep 2022 05:41:47 +0000 (+0900) Subject: monitor: lib: Support Unix domain socket (UDS) and TCP/IP socket concurrently X-Git-Tag: accepted/tizen/unified/20220908.013431~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1bbc88af8380214499fdeac39f34ff1f8c0322b1;p=platform%2Fcore%2Fsystem%2Fpass.git monitor: lib: Support Unix domain socket (UDS) and TCP/IP socket concurrently Previous TCP/IP socket-based IPC has a security issue that anyone can access the opened port without credential. Since UDS is exported as a file, we can apply file-based access control to it. So, we use UDS instead of TCP/IP socket by default. At the same time, we also support TCP/IP socket for resource-monitor-tool which is a web-based monitoring tool in user space. In the future, we will support TCP/IP socket only in debugging mode which is turned on/off by root- privileged command line tool. Change-Id: Id46a5e7560cf95d09f31222e5022ce3ea209753a Signed-off-by: Sung-hun Kim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ea606a..18f595b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,6 +123,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATI INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.json DESTINATION /etc/pass) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.json DESTINATION /etc/pass) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service @ONLY) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}-resource-monitor.socket.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}-resource-monitor.socket @ONLY) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.pass.service DESTINATION /usr/share/dbus-1/system-services) INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.thermal.service DESTINATION /usr/share/dbus-1/system-services) @@ -131,6 +132,11 @@ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/s PATTERN "${PROJECT_NAME}.service" ) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/system + FILES_MATCHING + PATTERN "${PROJECT_NAME}-resource-monitor.socket" + ) + ADD_SUBDIRECTORY(tests/integration-test) ADD_SUBDIRECTORY(tests/haltest) ADD_SUBDIRECTORY(tests/unittest) diff --git a/lib/resource-monitor/resource-monitor.c b/lib/resource-monitor/resource-monitor.c index a7ab07e..7a08699 100644 --- a/lib/resource-monitor/resource-monitor.c +++ b/lib/resource-monitor/resource-monitor.c @@ -30,11 +30,11 @@ #include #include #include +#include #include #include #include #include - #include #include "resource-monitor.h" @@ -289,8 +289,9 @@ static inline int handle_request(struct request_data *data) EXPORT int pass_resource_monitor_init(void) { + const char *server_socket_path = "/run/.pass-resource-monitor.socket"; struct pass_resource_monitor_client *client; - struct sockaddr_in server_addr; + struct sockaddr_un server_addr; int ret = TIZEN_ERROR_NO_DATA; if (!is_privilege_supported(PRIVILEGE_SYSTEMMONITOR)) @@ -303,19 +304,16 @@ int pass_resource_monitor_init(void) } /* open socket to server */ - client->id = socket(AF_INET, SOCK_STREAM, 0); + client->id = socket(AF_UNIX, SOCK_STREAM, 0); if (client->id < 0) { _E("[libpass] socket creation error"); goto err_out_free; } - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(REQUEST_SERVER_PORT); - - if (inet_pton(AF_INET, REQUEST_SERVER_IP, &server_addr.sin_addr) <= 0) { - _E("[libpass] invalid address"); - goto err_out_close; - } + bzero(&server_addr, sizeof(server_addr)); + server_addr.sun_family = AF_UNIX; + strncpy(server_addr.sun_path, server_socket_path, sizeof(server_addr.sun_path)); + server_addr.sun_path[sizeof(server_addr.sun_path) - 1] = '\0'; if (connect(client->id, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { diff --git a/packaging/pass.spec b/packaging/pass.spec index 4444495..dac786f 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -94,6 +94,7 @@ rm -rf %{buildroot} %make_install %install_service delayed.target.wants %{daemon_name}.service +%install_service sockets.target.wants %{daemon_name}-resource-monitor.socket %post @@ -119,7 +120,9 @@ systemctl daemon-reload %{_bindir}/%{daemon_name} %{_bindir}/resource-monitor %{_unitdir}/delayed.target.wants/%{daemon_name}.service +%{_unitdir}/sockets.target.wants/%{daemon_name}-resource-monitor.socket %{_unitdir}/%{daemon_name}.service +%{_unitdir}/%{daemon_name}-resource-monitor.socket %{_datadir}/dbus-1/system-services/org.tizen.system.pass.service %{_datadir}/dbus-1/system-services/org.tizen.system.thermal.service diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 5d30833..324d0fc 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1078,53 +1079,129 @@ static int create_request_client(int socket_fd) return 0; } -static int request_server_func(void *ctx, void **result) +static int init_unix_socket(int *sock, struct sockaddr_un *address, int *addrlen) { - struct sockaddr_in address; - struct timeval wait; + const char *server_unix_socket_path = "/run/.pass-resource-monitor.socket"; int opt = true; - int server_socket; - int addrlen; - int ret; - fd_set fds; - if (!g_request_server_run) - return THREAD_RETURN_DONE; - - init_resource_id(); + if (!sock || !address || !addrlen) + return -EINVAL; - /* 0. initialize server socket */ - server_socket = socket(AF_INET, SOCK_STREAM, 0); - if (server_socket < 0) { + *sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (*sock < 0) { _E("Failed to initialize socket"); goto error_out; } - if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, + if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { _E("Failed to setsockopt"); goto error_out_close; } - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(REQUEST_SERVER_PORT); + bzero(address, sizeof(*address)); + address->sun_family = AF_UNIX; + strncpy(address->sun_path, server_unix_socket_path, sizeof(address->sun_path)); + address->sun_path[sizeof(address->sun_path) - 1] = '\0'; + + if (!access(server_unix_socket_path, F_OK)) + unlink(server_unix_socket_path); - if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { + if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) { _E("Failed to bind"); goto error_out_close; } - if (listen(server_socket, PENDING_MAX) < 0) { + if (listen(*sock, PENDING_MAX) < 0) { _E("Failed to begin listenning"); goto error_out_close; } - addrlen = sizeof(address); + *addrlen = sizeof(*address); + + return 0; + +error_out_close: + close(*sock); +error_out: + return -EIO; +} + +int init_ip_socket(int *sock, struct sockaddr_in *address, int *addrlen) +{ + int opt = true; + + if (!sock || !address || !addrlen) + return -EINVAL; + + *sock = socket(AF_INET, SOCK_STREAM, 0); + if (*sock < 0) { + _E("Failed to initialize TCP/IP socket"); + goto error_out; + } + + if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&opt, sizeof(opt)) < 0) { + _E("Failed to setsockopt for TCP/IP socket"); + goto error_out_close; + } + + bzero(address, sizeof(*address)); + address->sin_family = AF_INET; + address->sin_addr.s_addr = INADDR_ANY; + address->sin_port = htons(REQUEST_SERVER_PORT); + + if (bind(*sock, (struct sockaddr *)address, sizeof(*address)) < 0) { + _E("Failed to bind for TCP/IP socket"); + goto error_out_close; + } + + if (listen(*sock, PENDING_MAX) < 0) { + _E("Failed to begin listenning for TCP/IP socket"); + goto error_out_close; + } + + *addrlen = sizeof(*address); + + return 0; + +error_out_close: + close(*sock); +error_out: + return -EIO; +} + +static int request_server_func(void *ctx, void **result) +{ + struct sockaddr_un unix_address; + struct sockaddr_in ip_address; + struct timeval wait; + int server_unix_socket; + int server_ip_socket; + int unix_addrlen; + int ip_addrlen; + int ret; + fd_set fds; + + if (!g_request_server_run) + return THREAD_RETURN_DONE; + + init_resource_id(); + + /* 0. initialize server socket */ + ret = init_unix_socket(&server_unix_socket, &unix_address, &unix_addrlen); + if (ret < 0) + goto error_out; + + /* initialize TCP socket */ + ret = init_ip_socket(&server_ip_socket, &ip_address, &ip_addrlen); + if (ret < 0) + goto error_out_close_server_unix_socket; while (g_request_server_run) { FD_ZERO(&fds); - FD_SET(server_socket, &fds); + FD_SET(server_unix_socket, &fds); + FD_SET(server_ip_socket, &fds); wait.tv_sec = 1; wait.tv_usec = 0; @@ -1135,9 +1212,21 @@ static int request_server_func(void *ctx, void **result) goto error_out_close; } - if (FD_ISSET(server_socket, &fds)) { - int new_socket = accept(server_socket, (struct sockaddr *)&address, - (socklen_t *)&addrlen); + if (FD_ISSET(server_unix_socket, &fds)) { + int new_socket = accept(server_unix_socket, (struct sockaddr *)&unix_address, + (socklen_t *)&unix_addrlen); + + if (new_socket < 0) { + _E("Failed to accept"); + goto error_out_close; + } + + create_request_client(new_socket); + } + + if (FD_ISSET(server_ip_socket, &fds)) { + int new_socket = accept(server_ip_socket, (struct sockaddr *)&ip_address, + (socklen_t *)&ip_addrlen); if (new_socket < 0) { _E("Failed to accept"); @@ -1148,12 +1237,15 @@ static int request_server_func(void *ctx, void **result) } } - close(server_socket); + close(server_ip_socket); + close(server_unix_socket); return THREAD_RETURN_DONE; error_out_close: - close(server_socket); + close(server_ip_socket); +error_out_close_server_unix_socket: + close(server_unix_socket); error_out: return THREAD_RETURN_ERROR; diff --git a/systemd/pass-resource-monitor.socket.in b/systemd/pass-resource-monitor.socket.in new file mode 100644 index 0000000..406f96f --- /dev/null +++ b/systemd/pass-resource-monitor.socket.in @@ -0,0 +1,10 @@ +[Unit] +Description=Pass resource-monitor socket + +[Socket] +SocketUser=system_fw +SocketGroup=system_fw +ListenStream=/run/.pass.socket +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@