Repository: fluent/fluent-bit (C)

Issue:
in_forward unix socket default permission
I want to set the permissions of the in_forward socket file in the same way as the in_syslog "unix_perm" option.

Currently, the permissions are changed from 755 to 666 after startup.

**Expected behavior**
```
[INPUT]
    name            forward
    tag             forward
    unix_path       /var/run/fluent-bit.sock
    unix_perm       0666
```

**Your Environment**
* Version used: Fluent Bit v1.9.3
* Configuration:
```
[INPUT]
    name            forward
    tag             forward
    unix_path       /var/run/fluent-bit.sock
```
* Operating System and version: linux ubuntu 20.04
* Filters and plugins: in_forward


Discussion:
I sent a patch https://github.com/fluent/fluent-bit/pull/5511



Patch:
diff --git a/plugins/in_forward/fw.c b/plugins/in_forward/fw.c
index 9fd969cd05f..0c2ef0737ff 100644
--- a/plugins/in_forward/fw.c
+++ b/plugins/in_forward/fw.c
@@ -26,6 +26,7 @@
 #ifdef FLB_HAVE_UNIX_SOCKET
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <sys/stat.h>
 #endif
 
 #include "fw.h"
@@ -60,6 +61,16 @@ static int fw_unix_create(struct flb_in_fw_config *ctx)
         return -1;
     }
 
+    if (ctx->unix_perm_str) {
+        if (chmod(address.sun_path, ctx->unix_perm)) {
+            flb_errno();
+            flb_plg_error(ctx->ins, "cannot set permission on '%s' to %04o",
+                      address.sun_path, ctx->unix_perm);
+            close(fd);
+            return -1;
+        }
+    }
+
     if (listen(fd, 5) != 0) {
         flb_errno();
         close(fd);
@@ -216,6 +227,11 @@ static struct flb_config_map config_map[] = {
     0, FLB_TRUE, offsetof(struct flb_in_fw_config, unix_path),
     "The path to unix socket to receive a Forward message."
    },
+    {
+     FLB_CONFIG_MAP_STR, "unix_perm", (char *)NULL,
+     0, FLB_TRUE, offsetof(struct flb_in_fw_config, unix_perm_str),
+     "Set the permissions for the UNIX socket"
+    },
    {
     FLB_CONFIG_MAP_SIZE, "buffer_chunk_size", FLB_IN_FW_CHUNK_SIZE,
     0, FLB_TRUE, offsetof(struct flb_in_fw_config, buffer_chunk_size),
diff --git a/plugins/in_forward/fw.h b/plugins/in_forward/fw.h
index 38d8709fe2f..ae1ff81d0a7 100644
--- a/plugins/in_forward/fw.h
+++ b/plugins/in_forward/fw.h
@@ -36,6 +36,8 @@ struct flb_in_fw_config {
 
     /* Unix Socket (TCP only) */
     char *unix_path;                /* Unix path for socket        */
+    unsigned int unix_perm;         /* Permission for socket       */
+    flb_sds_t unix_perm_str;        /* Permission (config map)     */
 
     int coll_fd;
     struct mk_list connections;     /* List of active connections */
diff --git a/plugins/in_forward/fw_config.c b/plugins/in_forward/fw_config.c
index 30c05b0dc36..9f662cd7ce5 100644
--- a/plugins/in_forward/fw_config.c
+++ b/plugins/in_forward/fw_config.c
@@ -53,6 +53,12 @@ struct flb_in_fw_config *fw_config_init(struct flb_input_instance *i_ins)
         snprintf(tmp, sizeof(tmp) - 1, "%d", i_ins->host.port);
         config->tcp_port = flb_strdup(tmp);
     }
+    else {
+        /* Unix socket mode */
+        if (config->unix_perm_str) {
+            config->unix_perm = strtol(config->unix_perm_str, NULL, 8) & 07777;
+        }
+    }
 
     if (!config->unix_path) {
         flb_debug("[in_fw] Listen='%s' TCP_Port=%s",


Test patch:
diff --git a/tests/runtime/in_forward.c b/tests/runtime/in_forward.c
index 60ca03efda5..fdf61da78fc 100644
--- a/tests/runtime/in_forward.c
+++ b/tests/runtime/in_forward.c
@@ -459,6 +459,110 @@ void flb_test_unix_path()
     flb_socket_close(fd);
     test_ctx_destroy(ctx);
 }
+
+
+void flb_test_unix_perm()
+{
+    struct flb_lib_out_cb cb_data;
+    struct test_ctx *ctx;
+    struct sockaddr_un sun;
+    flb_sockfd_t fd;
+    int ret;
+    int num;
+    ssize_t w_size;
+    char *unix_path = "in_forward_unix";
+    struct stat sb;
+
+    char *buf;
+    size_t size;
+
+    clear_output_num();
+
+    cb_data.cb = cb_check_result_json;
+    cb_data.data = "\"test\":\"msg\"";
+
+    ctx = test_ctx_create(&cb_data);
+    if (!TEST_CHECK(ctx != NULL)) {
+        TEST_MSG("test_ctx_create failed");
+        exit(EXIT_FAILURE);
+    }
+
+    ret = flb_input_set(ctx->flb, ctx->i_ffd,
+                        "unix_path", unix_path,
+                        "unix_perm", "0600",
+                        NULL);
+    TEST_CHECK(ret == 0);
+
+    ret = flb_output_set(ctx->flb, ctx->o_ffd,
+                         "match", "test",
+                         "format", "json",
+                         NULL);
+    TEST_CHECK(ret == 0);
+
+    /* Start the engine */
+    ret = flb_start(ctx->flb);
+    TEST_CHECK(ret == 0);
+
+    /* waiting to create socket */
+    flb_time_msleep(200); 
+
+    memset(&sun, 0, sizeof(sun));
+    fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if (!TEST_CHECK(fd >= 0)) {
+        TEST_MSG("failed to socket %s, errno=%d", unix_path, errno);
+        unlink(unix_path);
+        exit(EXIT_FAILURE);
+    }
+
+    sun.sun_family = AF_LOCAL;
+    strcpy(sun.sun_path, unix_path);
+    ret = connect(fd, (const struct sockaddr *)&sun, sizeof(sun));
+    if (!TEST_CHECK(ret >= 0)) {
+        TEST_MSG("failed to connect, errno=%d", errno);
+        flb_socket_close(fd);
+        unlink(unix_path);
+        exit(EXIT_FAILURE);
+    }
+    create_simple_json(&buf, &size);
+    w_size = send(fd, buf, size, 0);
+    flb_free(buf);
+    if (!TEST_CHECK(w_size == size)) {
+        TEST_MSG("failed to write to %s", unix_path);
+        flb_socket_close(fd);
+        unlink(unix_path);
+        exit(EXIT_FAILURE);
+    }
+
+    /* waiting to flush */
+    flb_time_msleep(1500);
+
+    num = get_output_num();
+    if (!TEST_CHECK(num > 0))  {
+        TEST_MSG("no outputs");
+    }
+
+
+    /* File permission */
+    ret = stat(unix_path, &sb);
+    if (!TEST_CHECK(ret == 0)) {
+        TEST_MSG("stat failed. errno=%d", errno);
+                test_ctx_destroy(ctx);
+        exit(EXIT_FAILURE);
+    }
+
+    if (!TEST_CHECK((sb.st_mode & S_IRWXO) == 0)) {
+        TEST_MSG("Permssion(others) error. val=0x%x",sb.st_mode & S_IRWXO);
+    }
+    if (!TEST_CHECK((sb.st_mode & S_IRWXG) == 0)) {
+        TEST_MSG("Permssion(group) error. val=0x%x",sb.st_mode & S_IRWXG);
+    }
+    if (!TEST_CHECK((sb.st_mode & S_IRWXU) == (S_IRUSR | S_IWUSR))) {
+        TEST_MSG("Permssion(user) error. val=0x%x",sb.st_mode & S_IRWXU);
+    }
+
+    flb_socket_close(fd);
+    test_ctx_destroy(ctx);
+}
 #endif /* FLB_HAVE_UNIX_SOCKET */
 
 
@@ -468,6 +572,7 @@ TEST_LIST = {
     {"tag_prefix", flb_test_tag_prefix},
 #ifdef FLB_HAVE_UNIX_SOCKET
     {"unix_path", flb_test_unix_path},
+    {"unix_perm", flb_test_unix_perm},
 #endif
     {NULL, NULL}
 };