1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/capsicum.h> 33 #include <sys/file.h> 34 #include <sys/stat.h> 35 36 #include <err.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <libgen.h> 40 #include <libutil.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <time.h> 46 #include <unistd.h> 47 48 struct pidfh { 49 int pf_dirfd; 50 int pf_fd; 51 char pf_dir[MAXPATHLEN + 1]; 52 char pf_filename[MAXPATHLEN + 1]; 53 dev_t pf_dev; 54 ino_t pf_ino; 55 }; 56 57 static int _pidfile_remove(struct pidfh *pfh, int freeit); 58 59 static int 60 pidfile_verify(const struct pidfh *pfh) 61 { 62 struct stat sb; 63 64 if (pfh == NULL || pfh->pf_fd == -1) 65 return (EDOOFUS); 66 /* 67 * Check remembered descriptor. 68 */ 69 if (fstat(pfh->pf_fd, &sb) == -1) 70 return (errno); 71 if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) 72 return (EDOOFUS); 73 return (0); 74 } 75 76 static int 77 pidfile_read_impl(int dirfd, const char *filename, pid_t *pidptr) 78 { 79 char buf[16], *endptr; 80 int error, fd, i; 81 82 fd = openat(dirfd, filename, O_RDONLY | O_CLOEXEC); 83 if (fd == -1) 84 return (errno); 85 86 i = read(fd, buf, sizeof(buf) - 1); 87 error = errno; /* Remember errno in case close() wants to change it. */ 88 close(fd); 89 if (i == -1) 90 return (error); 91 else if (i == 0) 92 return (EAGAIN); 93 buf[i] = '\0'; 94 95 *pidptr = strtol(buf, &endptr, 10); 96 if (endptr != &buf[i]) 97 return (EINVAL); 98 99 return (0); 100 } 101 102 static int 103 pidfile_read(int dirfd, const char *filename, pid_t *pidptr) 104 { 105 struct timespec rqtp; 106 int count; 107 108 count = 20; 109 rqtp.tv_sec = 0; 110 rqtp.tv_nsec = 5000000; 111 for (;;) { 112 errno = pidfile_read_impl(dirfd, filename, pidptr); 113 if (errno != EAGAIN || --count == 0) 114 break; 115 nanosleep(&rqtp, 0); 116 } 117 if (errno == EAGAIN) 118 *pidptr = -1; 119 return (errno); 120 } 121 122 struct pidfh * 123 pidfile_open(const char *pathp, mode_t mode, pid_t *pidptr) 124 { 125 char path[MAXPATHLEN]; 126 struct pidfh *pfh; 127 struct stat sb; 128 int error, fd, dirfd, dirlen, filenamelen; 129 cap_rights_t caprights; 130 131 pfh = malloc(sizeof(*pfh)); 132 if (pfh == NULL) 133 return (NULL); 134 135 if (pathp == NULL) { 136 dirlen = snprintf(pfh->pf_dir, sizeof(pfh->pf_dir), 137 "/var/run/"); 138 filenamelen = snprintf(pfh->pf_filename, 139 sizeof(pfh->pf_filename), "%s.pid", getprogname()); 140 } else { 141 if (strlcpy(path, pathp, sizeof(path)) >= sizeof(path)) { 142 free(pfh); 143 errno = ENAMETOOLONG; 144 return (NULL); 145 } 146 dirlen = strlcpy(pfh->pf_dir, dirname(path), 147 sizeof(pfh->pf_dir)); 148 (void)strlcpy(path, pathp, sizeof(path)); 149 filenamelen = strlcpy(pfh->pf_filename, basename(path), 150 sizeof(pfh->pf_filename)); 151 } 152 153 if (dirlen >= (int)sizeof(pfh->pf_dir) || 154 filenamelen >= (int)sizeof(pfh->pf_filename)) { 155 free(pfh); 156 errno = ENAMETOOLONG; 157 return (NULL); 158 } 159 160 dirfd = open(pfh->pf_dir, O_CLOEXEC | O_DIRECTORY | O_NONBLOCK); 161 if (dirfd == -1) { 162 error = errno; 163 free(pfh); 164 errno = error; 165 return (NULL); 166 } 167 168 /* 169 * Open the PID file and obtain exclusive lock. 170 * We truncate PID file here only to remove old PID immediately, 171 * PID file will be truncated again in pidfile_write(), so 172 * pidfile_write() can be called multiple times. 173 */ 174 fd = flopenat(dirfd, pfh->pf_filename, 175 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode); 176 if (fd == -1) { 177 if (errno == EWOULDBLOCK) { 178 if (pidptr == NULL) { 179 errno = EEXIST; 180 } else { 181 errno = pidfile_read(dirfd, 182 pfh->pf_filename, pidptr); 183 if (errno == 0 || errno == EAGAIN) 184 errno = EEXIST; 185 } 186 } 187 error = errno; 188 close(dirfd); 189 free(pfh); 190 errno = error; 191 return (NULL); 192 } 193 194 /* 195 * Remember file information, so in pidfile_write() we are sure we write 196 * to the proper descriptor. 197 */ 198 if (fstat(fd, &sb) == -1) { 199 goto failed; 200 } 201 202 if (cap_rights_limit(dirfd, 203 cap_rights_init(&caprights, CAP_UNLINKAT)) < 0 && errno != ENOSYS) { 204 goto failed; 205 } 206 207 if (cap_rights_limit(fd, cap_rights_init(&caprights, CAP_PWRITE, 208 CAP_FSTAT, CAP_FTRUNCATE, CAP_EVENT)) < 0 && 209 errno != ENOSYS) { 210 goto failed; 211 } 212 213 pfh->pf_dirfd = dirfd; 214 pfh->pf_fd = fd; 215 pfh->pf_dev = sb.st_dev; 216 pfh->pf_ino = sb.st_ino; 217 218 return (pfh); 219 220 failed: 221 error = errno; 222 unlinkat(dirfd, pfh->pf_filename, 0); 223 close(dirfd); 224 close(fd); 225 free(pfh); 226 errno = error; 227 return (NULL); 228 } 229 230 int 231 pidfile_write(struct pidfh *pfh) 232 { 233 char pidstr[16]; 234 int error, fd; 235 236 /* 237 * Check remembered descriptor, so we don't overwrite some other 238 * file if pidfile was closed and descriptor reused. 239 */ 240 errno = pidfile_verify(pfh); 241 if (errno != 0) { 242 /* 243 * Don't close descriptor, because we are not sure if it's ours. 244 */ 245 return (-1); 246 } 247 fd = pfh->pf_fd; 248 249 /* 250 * Truncate PID file, so multiple calls of pidfile_write() are allowed. 251 */ 252 if (ftruncate(fd, 0) == -1) { 253 error = errno; 254 _pidfile_remove(pfh, 0); 255 errno = error; 256 return (-1); 257 } 258 259 snprintf(pidstr, sizeof(pidstr), "%u", getpid()); 260 if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { 261 error = errno; 262 _pidfile_remove(pfh, 0); 263 errno = error; 264 return (-1); 265 } 266 267 return (0); 268 } 269 270 int 271 pidfile_close(struct pidfh *pfh) 272 { 273 int error; 274 275 error = pidfile_verify(pfh); 276 if (error != 0) { 277 errno = error; 278 return (-1); 279 } 280 281 if (close(pfh->pf_fd) == -1) 282 error = errno; 283 if (close(pfh->pf_dirfd) == -1 && error == 0) 284 error = errno; 285 286 free(pfh); 287 if (error != 0) { 288 errno = error; 289 return (-1); 290 } 291 return (0); 292 } 293 294 static int 295 _pidfile_remove(struct pidfh *pfh, int freeit) 296 { 297 int error; 298 299 error = pidfile_verify(pfh); 300 if (error != 0) { 301 errno = error; 302 return (-1); 303 } 304 305 if (funlinkat(pfh->pf_dirfd, pfh->pf_filename, pfh->pf_fd, 0) == -1) { 306 if (errno == EDEADLK) 307 return (-1); 308 error = errno; 309 } 310 if (close(pfh->pf_fd) == -1 && error == 0) 311 error = errno; 312 if (close(pfh->pf_dirfd) == -1 && error == 0) 313 error = errno; 314 if (freeit) 315 free(pfh); 316 else 317 pfh->pf_fd = -1; 318 if (error != 0) { 319 errno = error; 320 return (-1); 321 } 322 return (0); 323 } 324 325 int 326 pidfile_remove(struct pidfh *pfh) 327 { 328 329 return (_pidfile_remove(pfh, 1)); 330 } 331 332 int 333 pidfile_fileno(const struct pidfh *pfh) 334 { 335 336 if (pfh == NULL || pfh->pf_fd == -1) { 337 errno = EDOOFUS; 338 return (-1); 339 } 340 return (pfh->pf_fd); 341 } 342 343 int 344 pidfile_signal(const char *pathp, int sig, pid_t *pidptr) 345 { 346 pid_t pid; 347 int fd; 348 349 fd = flopenat(AT_FDCWD, pathp, 350 O_RDONLY | O_CLOEXEC | O_NONBLOCK); 351 if (fd >= 0) { 352 /* 353 * The file exists but is not locked, 354 * so the daemon is dead. Nothing to do. 355 */ 356 close(fd); 357 errno = ENOENT; 358 return (errno); 359 } 360 if (errno != EWOULDBLOCK) { 361 return (errno); 362 } 363 errno = pidfile_read(AT_FDCWD, pathp, &pid); 364 if (errno != 0) 365 return (errno); 366 /* 367 * Refuse to send broadcast or group signals, this has 368 * happened due to the bugs in pidfile(3). 369 */ 370 if (pid <= 0) 371 return (EDOM); 372 kill(pid, sig); 373 if (pidptr != NULL) 374 *pidptr = pid; 375 return (errno); 376 } 377