|
37 | 37 | #include <sys/syscall.h> |
38 | 38 | #endif |
39 | 39 |
|
| 40 | +#ifdef HAVE_SYS_PRCTL_H |
| 41 | +#include <sys/prctl.h> |
| 42 | +#endif |
| 43 | + |
40 | 44 | #ifdef _WIN32 |
41 | 45 | #define mkdir(d,m) _mkdir(d) |
42 | 46 | #endif |
@@ -944,8 +948,183 @@ int rep_usleep(useconds_t sec) |
944 | 948 | #ifndef HAVE_SETPROCTITLE |
945 | 949 | void rep_setproctitle(const char *fmt, ...) |
946 | 950 | { |
| 951 | +#if defined(HAVE_PRCTL) && defined(PR_SET_MM_MAP) && defined(__NR_brk) |
| 952 | + /* |
| 953 | + * Implementation based on setproctitle from lcx under LGPL-2.1+ |
| 954 | + * https://github.com/lxc/lxc/ |
| 955 | + * |
| 956 | + * Using PR_SET_MM_MAP requires CAP_SYS_RESOURCE. |
| 957 | + */ |
| 958 | + static char *proctitle = NULL; |
| 959 | + char *tmp_proctitle = NULL; |
| 960 | + char buf[2048] = {0}; |
| 961 | + char title[2048] = {0}; |
| 962 | + va_list ap; |
| 963 | + char *ptr = NULL; |
| 964 | + FILE *f = NULL; |
| 965 | + size_t title_len; |
| 966 | + int ret = 0; |
| 967 | + struct prctl_mm_map prctl_map = { |
| 968 | + .exe_fd = -1, |
| 969 | + }; |
| 970 | + long brk_val = 0; |
| 971 | + /* See `man proc_pid_stat.5` */ |
| 972 | + unsigned long start_code = 0; // 26 |
| 973 | + unsigned long end_code = 0; // 27 |
| 974 | + unsigned long start_stack = 0; // 28 |
| 975 | + |
| 976 | + unsigned long start_data = 0; // 45 |
| 977 | + unsigned long end_data = 0; // 46 |
| 978 | + unsigned long start_brk = 0; // 47 |
| 979 | + unsigned long arg_start = 0; // 48 |
| 980 | + unsigned long arg_end = 0; // 49 |
| 981 | + unsigned long env_start = 0; // 50 |
| 982 | + unsigned long env_end = 0; // 51 |
| 983 | + |
| 984 | + f = fopen("/proc/self/stat", "r"); |
| 985 | + if (f == NULL) { |
| 986 | + return; |
| 987 | + } |
| 988 | + |
| 989 | + ptr = fgets(buf, sizeof(buf), f); |
| 990 | + fclose(f); |
| 991 | + if (ptr == NULL) { |
| 992 | + return; |
| 993 | + } |
| 994 | + |
| 995 | + /* |
| 996 | + * Find the last ')' to skip the comm field which can contain spaces and |
| 997 | + * maybe ')'. |
| 998 | + */ |
| 999 | + ptr = strrchr(buf, ')'); |
| 1000 | + if (ptr == NULL || ptr[1] == '\0') { |
| 1001 | + return; |
| 1002 | + } |
| 1003 | + ptr += 2; // Skip ') ' |
| 1004 | + |
| 1005 | + /* See `man proc_pid_stat.5` */ |
| 1006 | + ret = sscanf( |
| 1007 | + ptr, |
| 1008 | + "%*c " // 3 (state) |
| 1009 | + "%*d " // 4 (ppid) |
| 1010 | + "%*d " // 5 (pgrp) |
| 1011 | + "%*d " // 6 (session) |
| 1012 | + "%*d " // 7 (tty_nr) |
| 1013 | + "%*d " // 8 (tpgid) |
| 1014 | + "%*u " // 9 (flags) |
| 1015 | + "%*u " // 10 (minflt) |
| 1016 | + "%*u " // 11 (cminflt) |
| 1017 | + "%*u " // 12 (majflt) |
| 1018 | + "%*u " // 13 (cmajflt) |
| 1019 | + "%*u " // 14 (utime) |
| 1020 | + "%*u " // 15 (stime) |
| 1021 | + "%*d " // 16 (cutime) |
| 1022 | + "%*d " // 17 (cstime) |
| 1023 | + "%*d " // 18 (priority) |
| 1024 | + "%*d " // 19 (nice) |
| 1025 | + "%*d " // 20 (num_threads) |
| 1026 | + "%*d " // 21 (itrealvalue) |
| 1027 | + "%*u " // 22 (starttime) |
| 1028 | + "%*u " // 23 (vsize) |
| 1029 | + "%*d " // 24 (rss) |
| 1030 | + "%*u " // 25 (rsslim) |
| 1031 | + "%lu " // 26 (start_code) |
| 1032 | + "%lu " // 27 (end_code) |
| 1033 | + "%lu " // 28 (start_stack) |
| 1034 | + "%*u " // 29 (kstkesp) |
| 1035 | + "%*u " // 30 (kstkeip) |
| 1036 | + "%*u " // 31 (signal) |
| 1037 | + "%*u " // 32 (blocked) |
| 1038 | + "%*u " // 33 (sigignore) |
| 1039 | + "%*u " // 34 (sigcatch) |
| 1040 | + "%*u " // 35 (wchan) |
| 1041 | + "%*u " // 36 (nswap) |
| 1042 | + "%*u " // 37 (cnswap) |
| 1043 | + "%*d " // 38 (exit_signal) |
| 1044 | + "%*d " // 39 (processor) |
| 1045 | + "%*d " // 40 (rt_priority) |
| 1046 | + "%*u " // 41 (policy) |
| 1047 | + "%*u " // 42 (delayacct_blkio_ticks) |
| 1048 | + "%*u " // 43 (guest_time) |
| 1049 | + "%*d " // 44 (cguest_time) |
| 1050 | + "%lu " // 45 (start_data) |
| 1051 | + "%lu " // 46 (end_data) |
| 1052 | + "%lu " // 47 (start_brk) |
| 1053 | + "%lu " // 48 (arg_start) |
| 1054 | + "%lu " // 49 (arg_end) |
| 1055 | + "%lu " // 50 (env_start) |
| 1056 | + "%lu", // 51 (env_end) |
| 1057 | + &start_code, // 26 |
| 1058 | + &end_code, // 27 |
| 1059 | + &start_stack, // 28 |
| 1060 | + &start_data, // 45 |
| 1061 | + &end_data, // 46 |
| 1062 | + &start_brk, // 47 |
| 1063 | + &arg_start, // 48 |
| 1064 | + &arg_end, // 49 |
| 1065 | + &env_start, // 50 |
| 1066 | + &env_end // 51 |
| 1067 | + ); |
| 1068 | + if (ret != 10) { |
| 1069 | + return; |
| 1070 | + } |
| 1071 | + |
| 1072 | + va_start(ap, fmt); |
| 1073 | + ret = vsnprintf(title, sizeof(title), fmt, ap); |
| 1074 | + va_end(ap); |
| 1075 | + if (ret <= 0) { |
| 1076 | + return; |
| 1077 | + } |
| 1078 | + /* |
| 1079 | + * Include the null byte here, because in the calculations below |
| 1080 | + * we want to have room for it. |
| 1081 | + */ |
| 1082 | + title_len = ret + 1; |
| 1083 | + |
| 1084 | + /* This will leak memory */ |
| 1085 | + tmp_proctitle = realloc(proctitle, title_len); |
| 1086 | + if (tmp_proctitle == NULL) { |
| 1087 | + return; |
| 1088 | + } |
| 1089 | + proctitle = tmp_proctitle; |
| 1090 | + |
| 1091 | + arg_start = (uint64_t)proctitle; |
| 1092 | + arg_end = arg_start + title_len; |
| 1093 | + |
| 1094 | + brk_val = syscall(__NR_brk, 0); |
| 1095 | + if (brk_val < 0) { |
| 1096 | + return; |
| 1097 | + } |
| 1098 | + |
| 1099 | + prctl_map = (struct prctl_mm_map) { |
| 1100 | + .start_code = start_code, |
| 1101 | + .end_code = end_code, |
| 1102 | + .start_stack = start_stack, |
| 1103 | + .start_data = start_data, |
| 1104 | + .end_data = end_data, |
| 1105 | + .start_brk = start_brk, |
| 1106 | + .brk = brk_val, |
| 1107 | + .arg_start = arg_start, |
| 1108 | + .arg_end = arg_end, |
| 1109 | + .env_start = env_start, |
| 1110 | + .env_end = env_end, |
| 1111 | + .auxv = NULL, |
| 1112 | + .auxv_size = 0, |
| 1113 | + .exe_fd = -1, |
| 1114 | + }; |
| 1115 | + |
| 1116 | + ret = prctl(PR_SET_MM, |
| 1117 | + PR_SET_MM_MAP, |
| 1118 | + (long)&prctl_map, |
| 1119 | + sizeof(prctl_map), |
| 1120 | + 0); |
| 1121 | + if (ret == 0) { |
| 1122 | + strlcpy((char *)arg_start, title, title_len); |
| 1123 | + } |
| 1124 | +#endif /* HAVE_PRCTL */ |
947 | 1125 | } |
948 | 1126 | #endif |
| 1127 | + |
949 | 1128 | #ifndef HAVE_SETPROCTITLE_INIT |
950 | 1129 | void rep_setproctitle_init(int argc, char *argv[], char *envp[]) |
951 | 1130 | { |
|
0 commit comments