Explorar el Código

utils: fix directory permission when create new log file.

Nick Peng hace 1 año
padre
commit
e0969e90d5
Se han modificado 3 ficheros con 143 adiciones y 133 borrados
  1. 8 132
      src/smartdns.c
  2. 129 1
      src/util.c
  3. 6 0
      src/util.h

+ 8 - 132
src/smartdns.c

@@ -36,10 +36,8 @@
 #include <fcntl.h>
 #include <getopt.h>
 #include <libgen.h>
-#include <linux/capability.h>
 #include <openssl/err.h>
 #include <openssl/ssl.h>
-#include <pwd.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -68,93 +66,6 @@ static int verbose_screen;
 static int exit_status;
 static int exit_restart;
 
-int capget(struct __user_cap_header_struct *header, struct __user_cap_data_struct *cap);
-int capset(struct __user_cap_header_struct *header, struct __user_cap_data_struct *cap);
-
-static int get_uid_gid(uid_t *uid, gid_t *gid)
-{
-	struct passwd *result = NULL;
-	struct passwd pwd;
-	char *buf = NULL;
-	ssize_t bufsize = 0;
-	int ret = -1;
-
-	if (dns_conf_user[0] == '\0') {
-		*uid = getuid();
-		*gid = getgid();
-		return 0;
-	}
-
-	bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-	if (bufsize == -1) {
-		bufsize = 1024 * 16;
-	}
-
-	buf = malloc(bufsize);
-	if (buf == NULL) {
-		goto out;
-	}
-
-	ret = getpwnam_r(dns_conf_user, &pwd, buf, bufsize, &result);
-	if (ret != 0) {
-		goto out;
-	}
-
-	if (result == NULL) {
-		ret = -1;
-		goto out;
-	}
-
-	*uid = result->pw_uid;
-	*gid = result->pw_gid;
-
-out:
-	if (buf) {
-		free(buf);
-	}
-
-	return ret;
-}
-
-static int drop_root_privilege(void)
-{
-	struct __user_cap_data_struct cap[2];
-	struct __user_cap_header_struct header;
-#ifdef _LINUX_CAPABILITY_VERSION_3
-	header.version = _LINUX_CAPABILITY_VERSION_3;
-#else
-	header.version = _LINUX_CAPABILITY_VERSION;
-#endif
-	header.pid = 0;
-	uid_t uid = 0;
-	gid_t gid = 0;
-	int unused __attribute__((unused)) = 0;
-
-	if (get_uid_gid(&uid, &gid) != 0) {
-		return -1;
-	}
-
-	memset(cap, 0, sizeof(cap));
-	if (capget(&header, cap) < 0) {
-		return -1;
-	}
-
-	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
-	for (int i = 0; i < 2; i++) {
-		cap[i].effective = (1 << CAP_NET_RAW | 1 << CAP_NET_ADMIN | 1 << CAP_NET_BIND_SERVICE);
-		cap[i].permitted = (1 << CAP_NET_RAW | 1 << CAP_NET_ADMIN | 1 << CAP_NET_BIND_SERVICE);
-	}
-
-	unused = setgid(gid);
-	unused = setuid(uid);
-	if (capset(&header, cap) < 0) {
-		return -1;
-	}
-
-	prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
-	return 0;
-}
-
 static void _help(void)
 {
 	/* clang-format off */
@@ -784,62 +695,27 @@ static void _reg_signal(void)
 
 static int _smartdns_create_logdir(void)
 {
-	uid_t uid = 0;
-	gid_t gid = 0;
-	struct stat sb;
-	char logdir[PATH_MAX] = {0};
-	int unused __attribute__((unused)) = 0;
-
-	safe_strncpy(logdir, _smartdns_log_path(), PATH_MAX);
-	dir_name(logdir);
-
-	if (get_uid_gid(&uid, &gid) != 0) {
-		return -1;
-	}
-
-	mkdir(logdir, 0750);
-	if (stat(logdir, &sb) == 0 && sb.st_uid == uid && sb.st_gid == gid && (sb.st_mode & 0700) == 0700) {
-		return 0;
-	}
-
-	if (chown(logdir, uid, gid) != 0) {
-		/* disable log */
+	int ret = create_dir_with_perm(_smartdns_log_path());
+	if (ret == -2) {
 		tlog_set_maxlog_count(0);
+	} else if (ret != 0) {
+		return -1;
 	}
 
-	unused = chmod(logdir, 0750);
-	unused = chown(_smartdns_log_path(), uid, gid);
 	return 0;
 }
 
 static int _smartdns_create_cache_dir(void)
 {
-	uid_t uid = 0;
-	gid_t gid = 0;
-	struct stat sb;
-	char cache_dir[PATH_MAX] = {0};
-	int unused __attribute__((unused)) = 0;
-
-	safe_strncpy(cache_dir, dns_conf_get_cache_dir(), PATH_MAX);
-	dir_name(cache_dir);
-
-	if (get_uid_gid(&uid, &gid) != 0) {
-		return -1;
-	}
-
-	mkdir(cache_dir, 0750);
-	if (stat(cache_dir, &sb) == 0 && sb.st_uid == uid && sb.st_gid == gid && (sb.st_mode & 0700) == 0700) {
-		return 0;
-	}
-
-	if (chown(cache_dir, uid, gid) != 0) {
+	int ret = create_dir_with_perm(dns_conf_get_cache_dir());
+	if (ret == -2) {
 		if (dns_conf_cache_file[0] == '\0') {
 			safe_strncpy(dns_conf_cache_file, SMARTDNS_TMP_CACHE_FILE, sizeof(dns_conf_cache_file));
 		}
+	} else if (ret != 0) {
+		return -1;
 	}
 
-	unused = chmod(cache_dir, 0750);
-	unused = chown(dns_conf_get_cache_dir(), uid, gid);
 	return 0;
 }
 

+ 129 - 1
src/util.c

@@ -41,6 +41,7 @@
 #include <openssl/x509v3.h>
 #include <poll.h>
 #include <pthread.h>
+#include <pwd.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
@@ -130,6 +131,93 @@ unsigned long get_tick_count(void)
 	return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
 }
 
+int get_uid_gid(uid_t *uid, gid_t *gid)
+{
+	struct passwd *result = NULL;
+	struct passwd pwd;
+	char *buf = NULL;
+	ssize_t bufsize = 0;
+	int ret = -1;
+
+	if (dns_conf_user[0] == '\0') {
+		*uid = getuid();
+		*gid = getgid();
+		return 0;
+	}
+
+	bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+	if (bufsize == -1) {
+		bufsize = 1024 * 16;
+	}
+
+	buf = malloc(bufsize);
+	if (buf == NULL) {
+		goto out;
+	}
+
+	ret = getpwnam_r(dns_conf_user, &pwd, buf, bufsize, &result);
+	if (ret != 0) {
+		goto out;
+	}
+
+	if (result == NULL) {
+		ret = -1;
+		goto out;
+	}
+
+	*uid = result->pw_uid;
+	*gid = result->pw_gid;
+
+out:
+	if (buf) {
+		free(buf);
+	}
+
+	return ret;
+}
+
+int capget(struct __user_cap_header_struct *header, struct __user_cap_data_struct *cap);
+int capset(struct __user_cap_header_struct *header, struct __user_cap_data_struct *cap);
+
+int drop_root_privilege(void)
+{
+	struct __user_cap_data_struct cap[2];
+	struct __user_cap_header_struct header;
+#ifdef _LINUX_CAPABILITY_VERSION_3
+	header.version = _LINUX_CAPABILITY_VERSION_3;
+#else
+	header.version = _LINUX_CAPABILITY_VERSION;
+#endif
+	header.pid = 0;
+	uid_t uid = 0;
+	gid_t gid = 0;
+	int unused __attribute__((unused)) = 0;
+
+	if (get_uid_gid(&uid, &gid) != 0) {
+		return -1;
+	}
+
+	memset(cap, 0, sizeof(cap));
+	if (capget(&header, cap) < 0) {
+		return -1;
+	}
+
+	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+	for (int i = 0; i < 2; i++) {
+		cap[i].effective = (1 << CAP_NET_RAW | 1 << CAP_NET_ADMIN | 1 << CAP_NET_BIND_SERVICE);
+		cap[i].permitted = (1 << CAP_NET_RAW | 1 << CAP_NET_ADMIN | 1 << CAP_NET_BIND_SERVICE);
+	}
+
+	unused = setgid(gid);
+	unused = setuid(uid);
+	if (capset(&header, cap) < 0) {
+		return -1;
+	}
+
+	prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+	return 0;
+}
+
 char *dir_name(char *path)
 {
 	if (strstr(path, "/") == NULL) {
@@ -140,6 +228,46 @@ char *dir_name(char *path)
 	return dirname(path);
 }
 
+int create_dir_with_perm(const char *dir_path)
+{
+	uid_t uid = 0;
+	gid_t gid = 0;
+	struct stat sb;
+	char data_dir[PATH_MAX] = {0};
+	int unused __attribute__((unused)) = 0;
+
+	safe_strncpy(data_dir, dir_path, PATH_MAX);
+	dir_name(data_dir);
+
+	if (get_uid_gid(&uid, &gid) != 0) {
+		return -1;
+	}
+
+	if (stat(data_dir, &sb) == 0) {
+		if (sb.st_uid == uid && sb.st_gid == gid && (sb.st_mode & 0700) == 0700) {
+			return 0;
+		}
+
+		if (sb.st_gid == gid && (sb.st_mode & 0070) == 0070) {
+			return 0;
+		}
+
+		if (sb.st_uid != uid && sb.st_gid != gid && (sb.st_mode & 0007) == 0007) {
+			return 0;
+		}
+	}
+
+	mkdir(data_dir, 0750);
+	if (chown(data_dir, uid, gid) != 0) {
+		return -2;
+	}
+
+	unused = chmod(data_dir, 0750);
+	unused = chown(dir_path, uid, gid);
+
+	return 0;
+}
+
 char *get_host_by_addr(char *host, int maxsize, struct sockaddr *addr)
 {
 	struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr;
@@ -1716,7 +1844,7 @@ void print_stack(void)
 	}
 }
 #else
-void print_stack(void) { }
+void print_stack(void) {}
 #endif
 
 void bug_ext(const char *file, int line, const char *func, const char *errfmt, ...)

+ 6 - 0
src/util.h

@@ -57,6 +57,12 @@ unsigned long get_tick_count(void);
 
 char *dir_name(char *path);
 
+int get_uid_gid(uid_t *uid, gid_t *gid);
+
+int drop_root_privilege(void);
+
+int create_dir_with_perm(const char *dir_path);
+
 char *get_host_by_addr(char *host, int maxsize, struct sockaddr *addr);
 
 int generate_random_addr(unsigned char *addr, int addr_len, int mask);