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 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/capsicum.h> 35 #include <sys/file.h> 36 #include <sys/stat.h> 37 38 #include <err.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <libgen.h> 42 #include <libutil.h> 43 #include <signal.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <time.h> 48 #include <unistd.h> 49 50 struct pidfh { 51 int pf_dirfd; 52 int pf_fd; 53 char pf_dir[MAXPATHLEN + 1]; 54 char pf_filename[MAXPATHLEN + 1]; 55 dev_t pf_dev; 56 ino_t pf_ino; 57 }; 58 59 static int _pidfile_remove(struct pidfh *pfh, int freeit); 60 61 static int 62 pidfile_verify(const struct pidfh *pfh) 63 { 64 struct stat sb; 65 66 if (pfh == NULL || pfh->pf_fd == -1) 67 return (EDOOFUS); 68 /* 69 * Check remembered descriptor. 70 */ 71 if (fstat(pfh->pf_fd, &sb) == -1) 72 return (errno); 73 if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) 74 return (EDOOFUS); 75 return (0); 76 } 77 78 static int 79 pidfile_read_impl(int dirfd, const char *filename, pid_t *pidptr) 80 { 81 char buf[16], *endptr; 82 int error, fd, i; 83 84 fd = openat(dirfd, filename, O_RDONLY | O_CLOEXEC); 85 if (fd == -1) 86 return (errno); 87 88 i = read(fd, buf, sizeof(buf) - 1); 89 error = errno; /* Remember errno in case close() wants to change it. */ 90 close(fd); 91 if (i == -1) 92 return (error); 93 else if (i == 0) 94 return (EAGAIN); 95 buf[i] = '\0'; 96 97 *pidptr = strtol(buf, &endptr, 10); 98 if (endptr != &buf[i]) 99 return (EINVAL); 100 101 return (0); 102 } 103 104 static int 105 pidfile_read(int dirfd, const char *filename, pid_t *pidptr) 106 { 107 struct timespec rqtp; 108 int count; 109 110 count = 20; 111 rqtp.tv_sec = 0; 112 rqtp.tv_nsec = 5000000; 113 for (;;) { 114 errno = pidfile_read_impl(dirfd, filename, pidptr); 115 if (errno != EAGAIN || --count == 0) 116 break; 117 nanosleep(&rqtp, 0); 118 } 119 if (errno == EAGAIN) 120 *pidptr = -1; 121 return (errno); 122 } 123 124 struct pidfh * 125 pidfile_open(const char *pathp, mode_t mode, pid_t *pidptr) 126 { 127 char path[MAXPATHLEN]; 128 struct pidfh *pfh; 129 struct stat sb; 130 int error, fd, dirfd, dirlen, filenamelen; 131 cap_rights_t caprights; 132 133 pfh = malloc(sizeof(*pfh)); 134 if (pfh == NULL) 135 return (NULL); 136 137 if (pathp == NULL) { 138 dirlen = snprintf(pfh->pf_dir, sizeof(pfh->pf_dir), 139 "/var/run/"); 140 filenamelen = snprintf(pfh->pf_filename, 141 sizeof(pfh->pf_filename), "%s.pid", getprogname()); 142 } else { 143 if (strlcpy(path, pathp, sizeof(path)) >= sizeof(path)) { 144 free(pfh); 145 errno = ENAMETOOLONG; 146 return (NULL); 147 } 148 dirlen = strlcpy(pfh->pf_dir, dirname(path), 149 sizeof(pfh->pf_dir)); 150 (void)strlcpy(path, pathp, sizeof(path)); 151 filenamelen = strlcpy(pfh->pf_filename, basename(path), 152 sizeof(pfh->pf_filename)); 153 } 154 155 if (dirlen >= (int)sizeof(pfh->pf_dir) || 156 filenamelen >= (int)sizeof(pfh->pf_filename)) { 157 free(pfh); 158 errno = ENAMETOOLONG; 159 return (NULL); 160 } 161 162 dirfd = open(pfh->pf_dir, O_CLOEXEC | O_DIRECTORY | O_NONBLOCK); 163 if (dirfd == -1) { 164 error = errno; 165 free(pfh); 166 errno = error; 167 return (NULL); 168 } 169 170 /* 171 * Open the PID file and obtain exclusive lock. 172 * We truncate PID file here only to remove old PID immediately, 173 * PID file will be truncated again in pidfile_write(), so 174 * pidfile_write() can be called multiple times. 175 */ 176 fd = flopenat(dirfd, pfh->pf_filename, 177 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode); 178 if (fd == -1) { 179 if (errno == EWOULDBLOCK) { 180 if (pidptr == NULL) { 181 errno = EEXIST; 182 } else { 183 errno = pidfile_read(dirfd, 184 pfh->pf_filename, pidptr); 185 if (errno == 0 || errno == EAGAIN) 186 errno = EEXIST; 187 } 188 } 189 error = errno; 190 close(dirfd); 191 free(pfh); 192 errno = error; 193 return (NULL); 194 } 195 196 /* 197 * Remember file information, so in pidfile_write() we are sure we write 198 * to the proper descriptor. 199 */ 200 if (fstat(fd, &sb) == -1) { 201 goto failed; 202 } 203 204 if (cap_rights_limit(dirfd, 205 cap_rights_init(&caprights, CAP_UNLINKAT)) < 0 && errno != ENOSYS) { 206 goto failed; 207 } 208 209 if (cap_rights_limit(fd, cap_rights_init(&caprights, CAP_PWRITE, 210 CAP_FSTAT, CAP_FTRUNCATE, CAP_EVENT)) < 0 && 211 errno != ENOSYS) { 212 goto failed; 213 } 214 215 pfh->pf_dirfd = dirfd; 216 pfh->pf_fd = fd; 217 pfh->pf_dev = sb.st_dev; 218 pfh->pf_ino = sb.st_ino; 219 220 return (pfh); 221 222 failed: 223 error = errno; 224 unlinkat(dirfd, pfh->pf_filename, 0); 225 close(dirfd); 226 close(fd); 227 free(pfh); 228 errno = error; 229 return (NULL); 230 } 231 232 int 233 pidfile_write(struct pidfh *pfh) 234 { 235 char pidstr[16]; 236 int error, fd; 237 238 /* 239 * Check remembered descriptor, so we don't overwrite some other 240 * file if pidfile was closed and descriptor reused. 241 */ 242 errno = pidfile_verify(pfh); 243 if (errno != 0) { 244 /* 245 * Don't close descriptor, because we are not sure if it's ours. 246 */ 247 return (-1); 248 } 249 fd = pfh->pf_fd; 250 251 /* 252 * Truncate PID file, so multiple calls of pidfile_write() are allowed. 253 */ 254 if (ftruncate(fd, 0) == -1) { 255 error = errno; 256 _pidfile_remove(pfh, 0); 257 errno = error; 258 return (-1); 259 } 260 261 snprintf(pidstr, sizeof(pidstr), "%u", getpid()); 262 if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { 263 error = errno; 264 _pidfile_remove(pfh, 0); 265 errno = error; 266 return (-1); 267 } 268 269 return (0); 270 } 271 272 int 273 pidfile_close(struct pidfh *pfh) 274 { 275 int error; 276 277 error = pidfile_verify(pfh); 278 if (error != 0) { 279 errno = error; 280 return (-1); 281 } 282 283 if (close(pfh->pf_fd) == -1) 284 error = errno; 285 if (close(pfh->pf_dirfd) == -1 && error == 0) 286 error = errno; 287 288 free(pfh); 289 if (error != 0) { 290 errno = error; 291 return (-1); 292 } 293 return (0); 294 } 295 296 static int 297 _pidfile_remove(struct pidfh *pfh, int freeit) 298 { 299 int error; 300 301 error = pidfile_verify(pfh); 302 if (error != 0) { 303 errno = error; 304 return (-1); 305 } 306 307 if (funlinkat(pfh->pf_dirfd, pfh->pf_filename, pfh->pf_fd, 0) == -1) { 308 if (errno == EDEADLK) 309 return (-1); 310 error = errno; 311 } 312 if (close(pfh->pf_fd) == -1 && error == 0) 313 error = errno; 314 if (close(pfh->pf_dirfd) == -1 && error == 0) 315 error = errno; 316 if (freeit) 317 free(pfh); 318 else 319 pfh->pf_fd = -1; 320 if (error != 0) { 321 errno = error; 322 return (-1); 323 } 324 return (0); 325 } 326 327 int 328 pidfile_remove(struct pidfh *pfh) 329 { 330 331 return (_pidfile_remove(pfh, 1)); 332 } 333 334 int 335 pidfile_fileno(const struct pidfh *pfh) 336 { 337 338 if (pfh == NULL || pfh->pf_fd == -1) { 339 errno = EDOOFUS; 340 return (-1); 341 } 342 return (pfh->pf_fd); 343 } 344 345 int 346 pidfile_signal(const char *pathp, int sig, pid_t *pidptr) 347 { 348 pid_t pid; 349 int fd; 350 351 fd = flopenat(AT_FDCWD, pathp, 352 O_RDONLY | O_CLOEXEC | O_NONBLOCK); 353 if (fd >= 0) { 354 /* 355 * The file exists but is not locked, 356 * so the daemon is dead. Nothing to do. 357 */ 358 close(fd); 359 errno = ENOENT; 360 return (errno); 361 } 362 if (errno != EWOULDBLOCK) { 363 return (errno); 364 } 365 errno = pidfile_read(AT_FDCWD, pathp, &pid); 366 if (errno != 0) 367 return (errno); 368 /* 369 * Refuse to send broadcast or group signals, this has 370 * happened due to the bugs in pidfile(3). 371 */ 372 if (pid <= 0) 373 return (EDOM); 374 kill(pid, sig); 375 if (pidptr != NULL) 376 *pidptr = pid; 377 return (errno); 378 } 379