1 /* $OpenBSD: shm_open.c,v 1.4 2013/11/12 06:09:48 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/types.h> 18 #include <sys/mman.h> 19 #include <sys/stat.h> 20 21 #include <errno.h> 22 #include <fcntl.h> 23 #include <limits.h> 24 #include <sha2.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 /* SHA256_DIGEST_STRING_LENGTH includes nul */ 31 /* "/tmp/" + sha256 + ".shm" */ 32 #define SHM_PATH_SIZE (5 + SHA256_DIGEST_STRING_LENGTH + 4) 33 34 static void 35 makeshmpath(const char *origpath, char *shmpath, size_t len) 36 { 37 char buf[SHA256_DIGEST_STRING_LENGTH]; 38 39 SHA256Data(origpath, strlen(origpath), buf); 40 snprintf(shmpath, len, "/tmp/%s.shm", buf); 41 } 42 43 int 44 shm_open(const char *path, int flags, mode_t mode) 45 { 46 char shmpath[SHM_PATH_SIZE]; 47 struct stat sb; 48 int fd; 49 50 if (flags & ~(O_RDONLY | O_RDWR | 51 O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC | O_NOFOLLOW)) { 52 errno = EINVAL; 53 return -1; 54 } 55 56 flags |= O_CLOEXEC | O_NOFOLLOW; 57 mode = mode & 0600; 58 59 makeshmpath(path, shmpath, sizeof(shmpath)); 60 61 fd = open(shmpath, flags, mode); 62 if (fd == -1) 63 return -1; 64 if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) { 65 close(fd); 66 errno = EINVAL; 67 return -1; 68 } 69 if (sb.st_uid != getuid()) { 70 close(fd); 71 errno = EPERM; 72 return -1; 73 } 74 return fd; 75 } 76 77 int 78 shm_unlink(const char *path) 79 { 80 char shmpath[SHM_PATH_SIZE]; 81 82 makeshmpath(path, shmpath, sizeof(shmpath)); 83 return unlink(shmpath); 84 } 85 86 char *_mktemp(char *); 87 88 int 89 shm_mkstemp(char *template) 90 { 91 size_t templatelen; 92 char *t; 93 int i, fd; 94 95 templatelen = strlen(template); 96 t = malloc(templatelen + 1); 97 if (!t) 98 return -1; 99 t[templatelen] = '\0'; 100 101 fd = -1; 102 for (i = 0; i < INT_MAX; i++) { 103 memcpy(t, template, templatelen); 104 if (!_mktemp(t)) 105 break; 106 fd = shm_open(t, O_RDWR | O_EXCL | O_CREAT, 0600); 107 if (fd != -1) { 108 memcpy(template, t, templatelen); 109 break; 110 } 111 } 112 113 free(t); 114 return fd; 115 } 116 117