]> git.sur5r.net Git - i3/i3/commitdiff
Create a secure temp path instead of a predictable one (Thanks Han)
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 18 Dec 2011 17:53:21 +0000 (17:53 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 18 Dec 2011 17:59:31 +0000 (17:59 +0000)
With this commit, i3 will now use either $XDG_RUNTIME_DIR/i3 (XDG_RUNTIME_DIR
is only writable by the user, so this is not a problem) or a secure temporary
location in /tmp, following the pattern /tmp/i3-<user>.XXXXXX

docs/ipc
docs/userguide
man/i3.man
src/util.c
testcases/t/159-socketpaths.t

index fc46590e0777d8973a5771e061c861631604a1a4..61a85c0a7a70ca91b98f80c3e57beacb27f8034b 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -11,8 +11,10 @@ workspace bar.
 The method of choice for IPC in our case is a unix socket because it has very
 little overhead on both sides and is usually available without headaches in
 most languages. In the default configuration file, the ipc-socket gets created
-in +/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the
-PID of i3. You can get the socketpath from i3 by calling +i3 --get-socketpath+.
+in +/tmp/i3-%u.XXXXXX/ipc-socket.%p+ where +%u+ is your UNIX username, +%p+ is
+the PID of i3 and XXXXXX is a string of random characters from the portable
+filename character set (see mkdtemp(3)). You can get the socketpath from i3 by
+calling +i3 --get-socketpath+.
 
 All i3 utilities, like +i3-msg+ and +i3-input+ will read the +I3_SOCKET_PATH+
 X11 property, stored on the X11 root window.
index 3d78d16f83020e1f838df9cd119dd7d24eb7bdd1..be8335efac40a5143d49fcdb5d1f3ef9138c2682 100644 (file)
@@ -643,16 +643,19 @@ programs to get information from i3, such as the current workspaces
 (to display a workspace bar), and to control i3.
 
 The IPC socket is enabled by default and will be created in
-+/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the PID
-of i3.
++/tmp/i3-%u.XXXXXX/ipc-socket.%p+ where +%u+ is your UNIX username, +%p+ is
+the PID of i3 and XXXXXX is a string of random characters from the portable
+filename character set (see mkdtemp(3)).
 
 You can override the default path through the environment-variable +I3SOCK+ or
 by specifying the +ipc-socket+ directive. This is discouraged, though, since i3
-does the right thing by default.
+does the right thing by default. If you decide to change it, it is strongly
+recommended to set this to a location in your home directory so that no other
+user can create that directory.
 
 *Examples*:
 ----------------------------
-ipc-socket /tmp/i3-ipc.sock
+ipc-socket ~/.i3/i3-ipc.sock
 ----------------------------
 
 You can then use the +i3-msg+ application to perform any command listed in
index 019c9124e54faf6a8ccb05f6f4b9418c957f61ab..2e14fce77071e7cf75ef057c2cfcf04155a45cd9 100644 (file)
@@ -294,9 +294,10 @@ exec /usr/bin/i3 -V -d all >> ~/.i3/logfile
 === I3SOCK
 
 This variable overwrites the IPC socket path (placed in
-/tmp/i3-%u/ipc-socket.%p by default, where %u is replaced with your UNIX
-username and %p is replaced with i3’s PID). The IPC socket is used by external
-programs like i3-msg(1) or i3bar(1).
+/tmp/i3-%u.XXXXXX/ipc-socket.%p by default, where %u is replaced with your UNIX
+username, %p is replaced with i3’s PID and XXXXXX is a string of random
+characters from the portable filename character set (see mkdtemp(3))). The IPC
+socket is used by external programs like i3-msg(1) or i3bar(1).
 
 == TODO
 
index 72146bff7aa7c1769a1d1d341255a738f1dfc62f..ba0b2c4b8be6dbe2ac22ae83b1824759885ff099 100644 (file)
@@ -234,25 +234,36 @@ static char **append_argument(char **original, char *argument) {
  *
  */
 char *get_process_filename(const char *prefix) {
-    char *dir = getenv("XDG_RUNTIME_DIR");
+    /* dir stores the directory path for this and all subsequent calls so that
+     * we only create a temporary directory once per i3 instance. */
+    static char *dir = NULL;
     if (dir == NULL) {
-        struct passwd *pw = getpwuid(getuid());
-        const char *username = pw ? pw->pw_name : "unknown";
-        sasprintf(&dir, "/tmp/i3-%s", username);
-    } else {
-        char *tmp;
-        sasprintf(&tmp, "%s/i3", dir);
-        dir = tmp;
-    }
-    if (!path_exists(dir)) {
-        if (mkdir(dir, 0700) == -1) {
-            perror("mkdir()");
-            return NULL;
+        /* Check if XDG_RUNTIME_DIR is set. If so, we use XDG_RUNTIME_DIR/i3 */
+        if ((dir = getenv("XDG_RUNTIME_DIR"))) {
+            char *tmp;
+            sasprintf(&tmp, "%s/i3", dir);
+            dir = tmp;
+            if (!path_exists(dir)) {
+                if (mkdir(dir, 0700) == -1) {
+                    perror("mkdir()");
+                    return NULL;
+                }
+            }
+        } else {
+            /* If not, we create a (secure) temp directory using the template
+             * /tmp/i3-<user>.XXXXXX */
+            struct passwd *pw = getpwuid(getuid());
+            const char *username = pw ? pw->pw_name : "unknown";
+            sasprintf(&dir, "/tmp/i3-%s.XXXXXX", username);
+            /* mkdtemp modifies dir */
+            if (mkdtemp(dir) == NULL) {
+                perror("mkdtemp()");
+                return NULL;
+            }
         }
     }
     char *filename;
     sasprintf(&filename, "%s/%s.%d", dir, prefix, getpid());
-    free(dir);
     return filename;
 }
 
index eb6bd79f1be5881b7d62f24847f959e5b6661ed0..b9cc9b631e1549d25f9c8eb31b99f6903ad6ac37 100644 (file)
@@ -20,9 +20,20 @@ EOT
 
 # ensure XDG_RUNTIME_DIR is not set
 delete $ENV{XDG_RUNTIME_DIR};
+
+# See which files exist in /tmp before to not mistakenly check an already
+# existing tmpdir of another i3 instance.
+my @files_before = </tmp/i3-*>;
 my $pid = launch_with_config($config, 1);
+my @files_after = </tmp/i3-*>;
+@files_after = grep { !($_ ~~ @files_before) } @files_after;
+
+is(@files_after, 1, 'one new temp directory');
 
 my $folder = "/tmp/i3-" . getpwuid(getuid());
+like($files_after[0], qr/^$folder/, 'temp directory matches expected pattern');
+$folder = $files_after[0];
+
 ok(-d $folder, "folder $folder exists");
 my $socketpath = "$folder/ipc-socket." . $pid;
 ok(-S $socketpath, "file $socketpath exists and is a socket");