-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
#include <pwd.h>
#include <netinet/ip.h>
#include <linux/kd.h>
+#include <dlfcn.h>
#include "macro.h"
#include "util.h"
#include "missing.h"
#include "log.h"
#include "strv.h"
-
-#if HAVE_SELINUX
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-
-static struct selabel_handle *label_hnd = NULL;
-
-static inline int use_selinux(void) {
- static int use_selinux_ind = -1;
-
- if (use_selinux_ind == -1)
- use_selinux_ind = (is_selinux_enabled() == 1);
-
- return use_selinux_ind;
-}
-
-static int label_get_file_label_from_path(
- const char *label,
- const char *path,
- const char *class,
- security_context_t *fcon) {
-
- security_context_t dir_con = NULL;
- security_class_t sclass;
- int r = 0;
-
- r = getfilecon(path, &dir_con);
- if (r >= 0) {
- r = -1;
- if ((sclass = string_to_security_class(class)) != 0)
- r = security_compute_create((security_context_t) label, dir_con, sclass, fcon);
- }
- if (r < 0)
- r = -errno;
-
- freecon(dir_con);
- return r;
-}
-
-#endif
-
-int label_init(void) {
- int r = 0;
-
-#if HAVE_SELINUX
- if (use_selinux()) {
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (!label_hnd) {
- log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m");
- r = (security_getenforce() == 1) ? -errno : 0;
- }
- }
-#endif
-
- return r;
-}
-
-int label_fix(const char *path) {
- int r = 0;
-#if HAVE_SELINUX
- struct stat st;
- security_context_t fcon;
- if (use_selinux()) {
- r = lstat(path, &st);
-
- if (r == 0) {
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
-
- if (r == 0) {
- r = setfilecon(path, fcon);
- freecon(fcon);
- }
- }
- if (r < 0) {
- log_error("Unable to fix label of %s: %m", path);
- r = (security_getenforce() == 1) ? -errno : 0;
- }
- }
-#endif
- return r;
-}
-
-void label_finish(void) {
-
-#if HAVE_SELINUX
- if (use_selinux())
- selabel_close(label_hnd);
-#endif
-
-}
-
-int label_get_socket_label_from_exe(
- const char *exe,
- char **label) {
- int r = 0;
-
-#if HAVE_SELINUX
- security_context_t mycon = NULL, fcon = NULL;
- security_class_t sclass;
-
- r = getcon(&mycon);
- if (r < 0)
- goto fail;
-
- r = getfilecon(exe, &fcon);
- if (r < 0)
- goto fail;
-
- sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
- if (r == 0)
- log_debug("SELinux Socket context for %s will be set to %s", exe, *label);
-
-fail:
- if (r< 0 && security_getenforce() == 1)
- r = -errno;
-
- freecon(mycon);
- freecon(fcon);
-#endif
-
- return r;
-}
-
-int label_fifofile_set(const char *label, const char *path) {
- int r = 0;
-
-#if HAVE_SELINUX
- security_context_t filecon = NULL;
- if (use_selinux() && label) {
- if (((r = label_get_file_label_from_path(label, path, "fifo_file", &filecon)) == 0)) {
- if ((r = setfscreatecon(filecon)) < 0) {
- log_error("Failed to set SELinux file context (%s) on %s: %m", label, path);
- r = -errno;
- }
-
- freecon(filecon);
- }
-
- if (r < 0 && security_getenforce() == 0)
- r = 0;
- }
-#endif
-
- return r;
-}
-
-int label_socket_set(const char *label) {
-
-#if HAVE_SELINUX
- if (use_selinux() && setsockcreatecon((security_context_t) label) < 0) {
- log_error("Failed to set SELinux context (%s) on socket: %m", label);
- if (security_getenforce() == 1)
- return -errno;
- }
-#endif
-
- return 0;
-}
-
-void label_file_clear(void) {
-
-#if HAVE_SELINUX
- if (use_selinux())
- setfscreatecon(NULL);
-#endif
-
- return;
-}
-
-void label_free(const char *label) {
-
-#if HAVE_SELINUX
- if (use_selinux())
- freecon((security_context_t) label);
-#endif
-
- return;
-}
-
-void label_socket_clear(void) {
-
-#if HAVE_SELINUX
- if (use_selinux())
- setsockcreatecon(NULL);
-#endif
-
- return;
-}
-
-static int label_mkdir(
- const char *path,
- mode_t mode) {
-
-#if HAVE_SELINUX
- int r;
- security_context_t fcon = NULL;
-
- if (use_selinux()) {
- if (path[0] == '/') {
- r = selabel_lookup_raw(label_hnd, &fcon, path, mode);
- }
- else {
- char *cwd = NULL;
- char *newpath = NULL;
- cwd = getcwd(NULL,0);
- if ((! cwd) || (asprintf(&newpath, "%s/%s",cwd,path) < 0)) {
- free(cwd);
- return -errno;
- }
- r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode);
- free(cwd);
- free(newpath);
- }
-
- if (r == 0)
- r = setfscreatecon(fcon);
-
- if ((r < 0) && (errno != ENOENT)) {
- log_error("Failed to set security context %s for %s", fcon, path);
-
- if (security_getenforce() == 1)
- goto finish;
- }
- }
- r = mkdir(path, mode);
-
-finish:
- if (use_selinux()) {
- setfscreatecon(NULL);
- freecon(fcon);
- }
-
- return r;
-#else
- return mkdir(path, mode);
-#endif
-}
+#include "label.h"
bool streq_ptr(const char *a, const char *b) {
if (t == (usec_t) -1)
return NULL;
+ if (t == 0) {
+ snprintf(p, l, "0");
+ p[l-1] = 0;
+ return p;
+ }
+
/* The result of this function can be parsed with parse_usec */
for (i = 0; i < ELEMENTSOF(table); i++) {
return strdup(u.sysname);
}
-int getmachineid_malloc(char **b) {
- int r;
-
- assert(b);
-
- if ((r = read_one_line_file("/var/lib/dbus/machine-id", b)) < 0)
- return r;
-
- strstrip(*b);
- return 0;
-}
-
char* getlogname_malloc(void) {
uid_t uid;
long bufsize;
int getttyname_malloc(char **r) {
char path[PATH_MAX], *p, *c;
+ int k;
assert(r);
- if (ttyname_r(STDIN_FILENO, path, sizeof(path)) < 0)
- return -errno;
+ if ((k = ttyname_r(STDIN_FILENO, path, sizeof(path))) != 0)
+ return -k;
char_array_0(path);
case VARIABLE:
if (*e == '}') {
- char *t;
+ const char *t;
- if ((t = strv_env_get_with_length(env, word+2, e-word-2))) {
- if (!(k = strappend(r, t)))
- goto fail;
+ if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
+ t = "";
- free(r);
- r = k;
+ if (!(k = strappend(r, t)))
+ goto fail;
- word = e+1;
- }
+ free(r);
+ r = k;
+ word = e+1;
state = WORD;
}
break;
STRV_FOREACH(i, argv) {
/* If $FOO appears as single word, replace it by the split up variable */
- if ((*i)[0] == '$') {
- char *e = strv_env_get(env, *i+1);
+ if ((*i)[0] == '$' && (*i)[1] != '{') {
+ char *e;
+ char **w, **m;
+ unsigned q;
- if (e) {
- char **w, **m;
- unsigned q;
+ if ((e = strv_env_get(env, *i+1))) {
if (!(m = strv_split_quoted(e))) {
r[k] = NULL;
strv_free(r);
return NULL;
}
+ } else
+ m = NULL;
- q = strv_length(m);
- l = l + q - 1;
+ q = strv_length(m);
+ l = l + q - 1;
- if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
- r[k] = NULL;
- strv_free(r);
- strv_free(m);
- return NULL;
- }
+ if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
+ r[k] = NULL;
+ strv_free(r);
+ strv_free(m);
+ return NULL;
+ }
- r = w;
+ r = w;
+ if (m) {
memcpy(r + k, m, q * sizeof(char*));
free(m);
-
- k += q;
- continue;
}
+
+ k += q;
+ continue;
}
/* If ${FOO} appears as part of a word, replace it by the variable as-is */
return r;
}
+void nss_disable_nscd(void) {
+
+ void (*func)(void);
+
+ /* This is an internal glibc function call. We are not
+ * supposed to call this, because we are not nscd. However
+ * sometimes we feel really dangerous and do it
+ * nonetheless. Muahahah! But at least we protect this with a
+ * dlsym() just in case glibc takes this away from us. */
+
+ if ((func = dlsym(RTLD_DEFAULT, "__nss_disable_nscd"))) {
+ log_debug("Disabling nscd.");
+ func();
+ } else
+ log_debug("Cannot disable nscd.");
+}
+
+int touch(const char *path) {
+ int fd;
+
+ assert(path);
+
+ if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666)) < 0)
+ return -errno;
+
+ close_nointr_nofail(fd);
+ return 0;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",