1 1.1.1.2 christos /* Copyright (C) 1991-2022 Free Software Foundation, Inc. 2 1.1 christos This file is part of the GNU C Library. 3 1.1 christos 4 1.1 christos The GNU C Library is free software; you can redistribute it and/or 5 1.1.1.2 christos modify it under the terms of the GNU Lesser General Public 6 1.1 christos License as published by the Free Software Foundation; either 7 1.1.1.2 christos version 2.1 of the License, or (at your option) any later version. 8 1.1 christos 9 1.1 christos The GNU C Library is distributed in the hope that it will be useful, 10 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 11 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 1.1.1.2 christos Lesser General Public License for more details. 13 1.1 christos 14 1.1.1.2 christos You should have received a copy of the GNU Lesser General Public 15 1.1 christos License along with the GNU C Library; if not, see 16 1.1 christos <https://www.gnu.org/licenses/>. */ 17 1.1 christos 18 1.1 christos #if !_LIBC 19 1.1 christos # include <libc-config.h> 20 1.1 christos # include "tempname.h" 21 1.1 christos #endif 22 1.1 christos 23 1.1 christos #include <sys/types.h> 24 1.1 christos #include <assert.h> 25 1.1.1.2 christos #include <stdbool.h> 26 1.1 christos 27 1.1 christos #include <errno.h> 28 1.1 christos 29 1.1 christos #include <stdio.h> 30 1.1 christos #ifndef P_tmpdir 31 1.1 christos # define P_tmpdir "/tmp" 32 1.1 christos #endif 33 1.1 christos #ifndef TMP_MAX 34 1.1 christos # define TMP_MAX 238328 35 1.1 christos #endif 36 1.1 christos #ifndef __GT_FILE 37 1.1 christos # define __GT_FILE 0 38 1.1 christos # define __GT_DIR 1 39 1.1 christos # define __GT_NOCREATE 2 40 1.1 christos #endif 41 1.1 christos #if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ 42 1.1 christos || GT_NOCREATE != __GT_NOCREATE) 43 1.1 christos # error report this to bug-gnulib@gnu.org 44 1.1 christos #endif 45 1.1 christos 46 1.1 christos #include <stddef.h> 47 1.1 christos #include <stdlib.h> 48 1.1 christos #include <string.h> 49 1.1 christos 50 1.1 christos #include <fcntl.h> 51 1.1.1.2 christos #include <stdalign.h> 52 1.1 christos #include <stdint.h> 53 1.1 christos #include <sys/random.h> 54 1.1 christos #include <sys/stat.h> 55 1.1.1.2 christos #include <time.h> 56 1.1 christos 57 1.1 christos #if _LIBC 58 1.1 christos # define struct_stat64 struct stat64 59 1.1 christos # define __secure_getenv __libc_secure_getenv 60 1.1 christos #else 61 1.1 christos # define struct_stat64 struct stat 62 1.1 christos # define __gen_tempname gen_tempname 63 1.1 christos # define __mkdir mkdir 64 1.1 christos # define __open open 65 1.1.1.2 christos # define __lstat64(file, buf) lstat (file, buf) 66 1.1.1.2 christos # define __stat64(file, buf) stat (file, buf) 67 1.1.1.2 christos # define __getrandom getrandom 68 1.1.1.2 christos # define __clock_gettime64 clock_gettime 69 1.1.1.2 christos # define __timespec64 timespec 70 1.1 christos #endif 71 1.1 christos 72 1.1 christos /* Use getrandom if it works, falling back on a 64-bit linear 73 1.1.1.2 christos congruential generator that starts with Var's value 74 1.1.1.2 christos mixed in with a clock's low-order bits if available. */ 75 1.1 christos typedef uint_fast64_t random_value; 76 1.1.1.2 christos #define RANDOM_VALUE_MAX UINT_FAST64_MAX 77 1.1.1.2 christos #define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ 78 1.1.1.2 christos #define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) 79 1.1.1.2 christos 80 1.1.1.2 christos static random_value 81 1.1.1.2 christos random_bits (random_value var, bool use_getrandom) 82 1.1.1.2 christos { 83 1.1.1.2 christos random_value r; 84 1.1.1.2 christos /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ 85 1.1.1.2 christos if (use_getrandom && __getrandom (&r, sizeof r, GRND_NONBLOCK) == sizeof r) 86 1.1.1.2 christos return r; 87 1.1.1.2 christos #if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME) 88 1.1.1.2 christos /* Add entropy if getrandom did not work. */ 89 1.1.1.2 christos struct __timespec64 tv; 90 1.1.1.2 christos __clock_gettime64 (CLOCK_MONOTONIC, &tv); 91 1.1.1.2 christos var ^= tv.tv_nsec; 92 1.1 christos #endif 93 1.1.1.2 christos return 2862933555777941757 * var + 3037000493; 94 1.1.1.2 christos } 95 1.1 christos 96 1.1 christos #if _LIBC 97 1.1 christos /* Return nonzero if DIR is an existent directory. */ 98 1.1 christos static int 99 1.1 christos direxists (const char *dir) 100 1.1 christos { 101 1.1 christos struct_stat64 buf; 102 1.1.1.2 christos return __stat64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); 103 1.1 christos } 104 1.1 christos 105 1.1 christos /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is 106 1.1 christos non-null and exists, uses it; otherwise uses the first of $TMPDIR, 107 1.1 christos P_tmpdir, /tmp that exists. Copies into TMPL a template suitable 108 1.1 christos for use with mk[s]temp. Will fail (-1) if DIR is non-null and 109 1.1 christos doesn't exist, none of the searched dirs exists, or there's not 110 1.1 christos enough space in TMPL. */ 111 1.1 christos int 112 1.1 christos __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, 113 1.1 christos int try_tmpdir) 114 1.1 christos { 115 1.1 christos const char *d; 116 1.1 christos size_t dlen, plen; 117 1.1 christos 118 1.1 christos if (!pfx || !pfx[0]) 119 1.1 christos { 120 1.1 christos pfx = "file"; 121 1.1 christos plen = 4; 122 1.1 christos } 123 1.1 christos else 124 1.1 christos { 125 1.1 christos plen = strlen (pfx); 126 1.1 christos if (plen > 5) 127 1.1 christos plen = 5; 128 1.1 christos } 129 1.1 christos 130 1.1 christos if (try_tmpdir) 131 1.1 christos { 132 1.1 christos d = __secure_getenv ("TMPDIR"); 133 1.1 christos if (d != NULL && direxists (d)) 134 1.1 christos dir = d; 135 1.1 christos else if (dir != NULL && direxists (dir)) 136 1.1 christos /* nothing */ ; 137 1.1 christos else 138 1.1 christos dir = NULL; 139 1.1 christos } 140 1.1 christos if (dir == NULL) 141 1.1 christos { 142 1.1 christos if (direxists (P_tmpdir)) 143 1.1 christos dir = P_tmpdir; 144 1.1 christos else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) 145 1.1 christos dir = "/tmp"; 146 1.1 christos else 147 1.1 christos { 148 1.1 christos __set_errno (ENOENT); 149 1.1 christos return -1; 150 1.1 christos } 151 1.1 christos } 152 1.1 christos 153 1.1 christos dlen = strlen (dir); 154 1.1 christos while (dlen > 1 && dir[dlen - 1] == '/') 155 1.1 christos dlen--; /* remove trailing slashes */ 156 1.1 christos 157 1.1 christos /* check we have room for "${dir}/${pfx}XXXXXX\0" */ 158 1.1 christos if (tmpl_len < dlen + 1 + plen + 6 + 1) 159 1.1 christos { 160 1.1 christos __set_errno (EINVAL); 161 1.1 christos return -1; 162 1.1 christos } 163 1.1 christos 164 1.1 christos sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); 165 1.1 christos return 0; 166 1.1 christos } 167 1.1 christos #endif /* _LIBC */ 168 1.1 christos 169 1.1 christos #if _LIBC 170 1.1 christos static int try_tempname_len (char *, int, void *, int (*) (char *, void *), 171 1.1 christos size_t); 172 1.1 christos #endif 173 1.1 christos 174 1.1 christos static int 175 1.1 christos try_file (char *tmpl, void *flags) 176 1.1 christos { 177 1.1 christos int *openflags = flags; 178 1.1 christos return __open (tmpl, 179 1.1 christos (*openflags & ~O_ACCMODE) 180 1.1 christos | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 181 1.1 christos } 182 1.1 christos 183 1.1 christos static int 184 1.1.1.2 christos try_dir (char *tmpl, _GL_UNUSED void *flags) 185 1.1 christos { 186 1.1 christos return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); 187 1.1 christos } 188 1.1 christos 189 1.1 christos static int 190 1.1.1.2 christos try_nocreate (char *tmpl, _GL_UNUSED void *flags) 191 1.1 christos { 192 1.1 christos struct_stat64 st; 193 1.1 christos 194 1.1.1.2 christos if (__lstat64 (tmpl, &st) == 0 || errno == EOVERFLOW) 195 1.1 christos __set_errno (EEXIST); 196 1.1 christos return errno == ENOENT ? 0 : -1; 197 1.1 christos } 198 1.1 christos 199 1.1 christos /* These are the characters used in temporary file names. */ 200 1.1 christos static const char letters[] = 201 1.1 christos "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 202 1.1 christos 203 1.1 christos /* Generate a temporary file name based on TMPL. TMPL must match the 204 1.1 christos rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s, 205 1.1 christos possibly with a suffix). 206 1.1 christos The name constructed does not exist at the time of the call to 207 1.1 christos this function. TMPL is overwritten with the result. 208 1.1 christos 209 1.1 christos KIND may be one of: 210 1.1 christos __GT_NOCREATE: simply verify that the name does not exist 211 1.1 christos at the time of the call. 212 1.1 christos __GT_FILE: create the file using open(O_CREAT|O_EXCL) 213 1.1 christos and return a read-write fd. The file is mode 0600. 214 1.1 christos __GT_DIR: create a directory, which will be mode 0700. 215 1.1 christos 216 1.1 christos We use a clever algorithm to get hard-to-predict names. */ 217 1.1 christos #ifdef _LIBC 218 1.1 christos static 219 1.1 christos #endif 220 1.1 christos int 221 1.1 christos gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, 222 1.1 christos size_t x_suffix_len) 223 1.1 christos { 224 1.1 christos static int (*const tryfunc[]) (char *, void *) = 225 1.1 christos { 226 1.1 christos [__GT_FILE] = try_file, 227 1.1 christos [__GT_DIR] = try_dir, 228 1.1 christos [__GT_NOCREATE] = try_nocreate 229 1.1 christos }; 230 1.1 christos return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind], 231 1.1 christos x_suffix_len); 232 1.1 christos } 233 1.1 christos 234 1.1 christos #ifdef _LIBC 235 1.1 christos static 236 1.1 christos #endif 237 1.1 christos int 238 1.1 christos try_tempname_len (char *tmpl, int suffixlen, void *args, 239 1.1 christos int (*tryfunc) (char *, void *), size_t x_suffix_len) 240 1.1 christos { 241 1.1 christos size_t len; 242 1.1 christos char *XXXXXX; 243 1.1 christos unsigned int count; 244 1.1 christos int fd = -1; 245 1.1 christos int save_errno = errno; 246 1.1 christos 247 1.1 christos /* A lower bound on the number of temporary files to attempt to 248 1.1 christos generate. The maximum total number of temporary file names that 249 1.1 christos can exist for a given template is 62**6. It should never be 250 1.1 christos necessary to try all of these combinations. Instead if a reasonable 251 1.1 christos number of names is tried (we define reasonable as 62**3) fail to 252 1.1 christos give the system administrator the chance to remove the problems. 253 1.1 christos This value requires that X_SUFFIX_LEN be at least 3. */ 254 1.1 christos #define ATTEMPTS_MIN (62 * 62 * 62) 255 1.1 christos 256 1.1 christos /* The number of times to attempt to generate a temporary file. To 257 1.1 christos conform to POSIX, this must be no smaller than TMP_MAX. */ 258 1.1 christos #if ATTEMPTS_MIN < TMP_MAX 259 1.1 christos unsigned int attempts = TMP_MAX; 260 1.1 christos #else 261 1.1 christos unsigned int attempts = ATTEMPTS_MIN; 262 1.1 christos #endif 263 1.1 christos 264 1.1.1.2 christos /* A random variable. The initial value is used only the for fallback path 265 1.1.1.2 christos on 'random_bits' on 'getrandom' failure. Its initial value tries to use 266 1.1.1.2 christos some entropy from the ASLR and ignore possible bits from the stack 267 1.1.1.2 christos alignment. */ 268 1.1.1.2 christos random_value v = ((uintptr_t) &v) / alignof (max_align_t); 269 1.1 christos 270 1.1 christos /* How many random base-62 digits can currently be extracted from V. */ 271 1.1 christos int vdigits = 0; 272 1.1 christos 273 1.1.1.2 christos /* Whether to consume entropy when acquiring random bits. On the 274 1.1.1.2 christos first try it's worth the entropy cost with __GT_NOCREATE, which 275 1.1.1.2 christos is inherently insecure and can use the entropy to make it a bit 276 1.1.1.2 christos less secure. On the (rare) second and later attempts it might 277 1.1.1.2 christos help against DoS attacks. */ 278 1.1.1.2 christos bool use_getrandom = tryfunc == try_nocreate; 279 1.1.1.2 christos 280 1.1 christos /* Least unfair value for V. If V is less than this, V can generate 281 1.1 christos BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ 282 1.1 christos random_value const unfair_min 283 1.1 christos = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; 284 1.1 christos 285 1.1 christos len = strlen (tmpl); 286 1.1 christos if (len < x_suffix_len + suffixlen 287 1.1 christos || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len) 288 1.1 christos { 289 1.1 christos __set_errno (EINVAL); 290 1.1 christos return -1; 291 1.1 christos } 292 1.1 christos 293 1.1 christos /* This is where the Xs start. */ 294 1.1 christos XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; 295 1.1 christos 296 1.1 christos for (count = 0; count < attempts; ++count) 297 1.1 christos { 298 1.1 christos for (size_t i = 0; i < x_suffix_len; i++) 299 1.1 christos { 300 1.1 christos if (vdigits == 0) 301 1.1 christos { 302 1.1 christos do 303 1.1.1.2 christos { 304 1.1.1.2 christos v = random_bits (v, use_getrandom); 305 1.1.1.2 christos use_getrandom = true; 306 1.1.1.2 christos } 307 1.1 christos while (unfair_min <= v); 308 1.1 christos 309 1.1 christos vdigits = BASE_62_DIGITS; 310 1.1 christos } 311 1.1 christos 312 1.1 christos XXXXXX[i] = letters[v % 62]; 313 1.1 christos v /= 62; 314 1.1 christos vdigits--; 315 1.1 christos } 316 1.1 christos 317 1.1 christos fd = tryfunc (tmpl, args); 318 1.1 christos if (fd >= 0) 319 1.1 christos { 320 1.1 christos __set_errno (save_errno); 321 1.1 christos return fd; 322 1.1 christos } 323 1.1 christos else if (errno != EEXIST) 324 1.1 christos return -1; 325 1.1 christos } 326 1.1 christos 327 1.1 christos /* We got out of the loop because we ran out of combinations to try. */ 328 1.1 christos __set_errno (EEXIST); 329 1.1 christos return -1; 330 1.1 christos } 331 1.1 christos 332 1.1 christos int 333 1.1 christos __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) 334 1.1 christos { 335 1.1 christos return gen_tempname_len (tmpl, suffixlen, flags, kind, 6); 336 1.1 christos } 337 1.1 christos 338 1.1 christos #if !_LIBC 339 1.1 christos int 340 1.1 christos try_tempname (char *tmpl, int suffixlen, void *args, 341 1.1 christos int (*tryfunc) (char *, void *)) 342 1.1 christos { 343 1.1 christos return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6); 344 1.1 christos } 345 1.1 christos #endif 346