From 8addd7913a743b75ef3854ab4a96fea81cc5245d Mon Sep 17 00:00:00 2001 From: William Hubbs Date: Fri, 4 Dec 2015 18:02:43 -0600 Subject: Create detect_container() and detect_vm() functions These functions replace rc_sys so that we can detect containers and vms separately. Also, we copy file_regex() to rc-misc.c and open it to all operating systems. --- src/includes/rc-misc.h | 4 ++ src/rc/rc-misc.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h index 3cce8d02..e0565b6b 100644 --- a/src/includes/rc-misc.h +++ b/src/includes/rc-misc.h @@ -87,4 +87,8 @@ int is_writable(const char *); #define service_stop(service) exec_service(service, "stop"); int parse_mode(mode_t *, char *); +const char *detect_prefix(void); +const char *get_systype(void); +const char *detect_container(void); +const char *detect_vm(void); #endif diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 27d9f818..1e2af0ab 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -34,12 +34,12 @@ #ifdef __linux__ # include -# include #endif #include #include #include +# include #include #include #include @@ -346,3 +346,160 @@ is_writable(const char *path) return 0; } + +static bool file_regex(const char *file, const char *regex) +{ + FILE *fp; + char *line = NULL; + size_t len = 0; + regex_t re; + bool retval = true; + int result; + + if (!(fp = fopen(file, "r"))) + return false; + + if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { + fclose(fp); + line = xmalloc(sizeof(char) * BUFSIZ); + regerror(result, &re, line, BUFSIZ); + fprintf(stderr, "file_regex: %s", line); + free(line); + return false; + } + + while ((rc_getline(&line, &len, fp))) { + char *str = line; + /* some /proc files have \0 separated content so we have to + loop through the 'line' */ + do { + if (regexec(&re, str, 0, NULL, 0) == 0) + goto found; + str += strlen(str) + 1; + /* len is the size of allocated buffer and we don't + want call regexec BUFSIZE times. find next str */ + while (str < line + len && *str == '\0') + str++; + } while (str < line + len); + } + retval = false; +found: + fclose(fp); + free(line); + regfree(&re); + + return retval; +} + +const char *detect_prefix(void) +{ +#ifdef PREFIX + return RC_SYS_PREFIX; +#else + return NULL; +#endif +} + +const char *get_systype(void) +{ + char *systype = rc_conf_value("rc_sys"); + if (systype) { + char *s = systype; + /* Convert to uppercase */ + while (s && *s) { + if (islower((unsigned char) *s)) + *s = toupper((unsigned char) *s); + s++; + } + } + return systype; +} + +const char *detect_container(void) +{ + char *systype = get_systype(); + +#ifdef __FreeBSD__ + if (systype && strcmp(systype, RC_SYS_JAIL) == 0) + return RC_SYS_JAIL; + int jailed = 0; + size_t len = sizeof(jailed); + + if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0) + if (jailed == 1) + return RC_SYS_JAIL; +#endif + +#ifdef __linux__ + if (systype) { + if (strcmp(systype, RC_SYS_UML) == 0) + return RC_SYS_UML; + if (strcmp(systype, RC_SYS_VSERVER) == 0) + return RC_SYS_VSERVER; + if (strcmp(systype, RC_SYS_OPENVZ) == 0) + return RC_SYS_OPENVZ; + if (strcmp(systype, RC_SYS_LXC) == 0) + return RC_SYS_LXC; + if (strcmp(systype, RC_SYS_RKT) == 0) + return RC_SYS_RKT; + if (strcmp(systype, RC_SYS_SYSTEMD_NSPAWN) == 0) + return RC_SYS_SYSTEMD_NSPAWN; + if (strcmp(systype, RC_SYS_DOCKER) == 0) + return RC_SYS_DOCKER; + } + if (file_regex("/proc/cpuinfo", "UML")) + return RC_SYS_UML; + else if (file_regex("/proc/self/status", + "(s_context|VxID):[[:space:]]*[1-9]")) + return RC_SYS_VSERVER; + else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version")) + return RC_SYS_OPENVZ; + else if (file_regex("/proc/self/status", + "envID:[[:space:]]*[1-9]")) + return RC_SYS_OPENVZ; /* old test */ + else if (file_regex("/proc/1/environ", "container=lxc")) + return RC_SYS_LXC; + else if (file_regex("/proc/1/environ", "container=rkt")) + return RC_SYS_RKT; + else if (file_regex("/proc/1/environ", "container=systemd-nspawn")) + return RC_SYS_SYSTEMD_NSPAWN; + else if (file_regex("/proc/1/environ", "container=docker")) + return RC_SYS_DOCKER; +#endif + + return NULL; +} + +const char *detect_vm(void) +{ + char *systype = get_systype(); + +#ifdef __NetBSD__ + if (systype) { + if(strcmp(systype, RC_SYS_XEN0) == 0) + return RC_SYS_XEN0; + if (strcmp(systype, RC_SYS_XENU) == 0) + return RC_SYS_XENU; + } + if (exists("/kern/xen/privcmd")) + return RC_SYS_XEN0; + if (exists("/kern/xen")) + return RC_SYS_XENU; +#endif + +#ifdef __linux__ + if (systype) { + if (strcmp(systype, RC_SYS_XEN0) == 0) + return RC_SYS_XEN0; + if (strcmp(systype, RC_SYS_XENU) == 0) + return RC_SYS_XENU; + } + if (exists("/proc/xen")) { + if (file_regex("/proc/xen/capabilities", "control_d")) + return RC_SYS_XEN0; + return RC_SYS_XENU; + } +#endif + + return NULL; +} -- cgit v1.2.3