chiark / gitweb /
env: considerably beef up environment cleaning logic
[elogind.git] / src / shared / util.c
index 37e383f2efb8224aad640eda64c04497d3d192b6..5b795d4a246e1e2be581479cb46acdd848b35647 100644 (file)
@@ -70,6 +70,7 @@
 #include "path-util.h"
 #include "exit-status.h"
 #include "hashmap.h"
+#include "env-util.h"
 
 int saved_argc = 0;
 char **saved_argv = NULL;
@@ -77,10 +78,6 @@ char **saved_argv = NULL;
 static volatile unsigned cached_columns = 0;
 static volatile unsigned cached_lines = 0;
 
-bool is_efiboot(void) {
-        return access("/sys/firmware/efi", F_OK) >= 0;
-}
-
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
         long r;
@@ -561,9 +558,9 @@ int fchmod_umask(int fd, mode_t m) {
 }
 
 int write_one_line_file_atomic(const char *fn, const char *line) {
-        FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *p = NULL;
         int r;
-        char *p;
 
         assert(fn);
         assert(line);
@@ -585,12 +582,9 @@ int write_one_line_file_atomic(const char *fn, const char *line) {
 
         fflush(f);
 
-        if (ferror(f)) {
-                if (errno != 0)
-                        r = -errno;
-                else
-                        r = -EIO;
-        } else {
+        if (ferror(f))
+                r = errno ? -errno : -EIO;
+        else {
                 if (rename(p, fn) < 0)
                         r = -errno;
                 else
@@ -601,9 +595,6 @@ finish:
         if (r < 0)
                 unlink(p);
 
-        fclose(f);
-        free(p);
-
         return r;
 }
 
@@ -3351,10 +3342,10 @@ char *replace_env(const char *format, char **env) {
                         if (*e == '}') {
                                 const char *t;
 
-                                if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
-                                        t = "";
+                                t = strempty(strv_env_get_n(env, word+2, e-word-2));
 
-                                if (!(k = strappend(r, t)))
+                                k = strappend(r, t);
+                                if (!k)
                                         goto fail;
 
                                 free(r);
@@ -3395,7 +3386,8 @@ char **replace_env_argv(char **argv, char **env) {
                         char **w, **m;
                         unsigned q;
 
-                        if ((e = strv_env_get(env, *i+1))) {
+                        e = strv_env_get(env, *i+1);
+                        if (e) {
 
                                 if (!(m = strv_split_quoted(e))) {
                                         r[k] = NULL;
@@ -5563,6 +5555,11 @@ void fclosep(FILE **f) {
                 fclose(*f);
 }
 
+void pclosep(FILE **f) {
+        if (*f)
+                pclose(*f);
+}
+
 void closep(int *fd) {
         if (*fd >= 0)
                 close_nointr_nofail(*fd);
@@ -5613,6 +5610,39 @@ bool string_is_safe(const char *p) {
         return true;
 }
 
+bool string_has_cc(const char *p) {
+        const char *t;
+
+        assert(p);
+
+        for (t = p; *t; t++)
+                if (*t > 0 && *t < ' ')
+                        return true;
+
+        return false;
+}
+
+bool path_is_safe(const char *p) {
+
+        if (isempty(p))
+                return false;
+
+        if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
+                return false;
+
+        if (strlen(p) > PATH_MAX)
+                return false;
+
+        /* The following two checks are not really dangerous, but hey, they still are confusing */
+        if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
+                return false;
+
+        if (strstr(p, "//"))
+                return false;
+
+        return true;
+}
+
 /* hey glibc, APIs with callbacks without a user pointer are so useless */
 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
                  int (*compar) (const void *, const void *, void *), void *arg) {