1*81064d43Sguenther /* $OpenBSD: shm_open.c,v 1.9 2017/09/10 18:20:00 guenther Exp $ */
244d38a94Stedu /*
344d38a94Stedu * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
444d38a94Stedu *
544d38a94Stedu * Permission to use, copy, modify, and distribute this software for any
644d38a94Stedu * purpose with or without fee is hereby granted, provided that the above
744d38a94Stedu * copyright notice and this permission notice appear in all copies.
844d38a94Stedu *
944d38a94Stedu * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1044d38a94Stedu * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1144d38a94Stedu * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1244d38a94Stedu * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1344d38a94Stedu * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1444d38a94Stedu * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1544d38a94Stedu * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1644d38a94Stedu */
1744d38a94Stedu #include <sys/types.h>
1844d38a94Stedu #include <sys/mman.h>
1944d38a94Stedu #include <sys/stat.h>
2044d38a94Stedu
2144d38a94Stedu #include <errno.h>
2244d38a94Stedu #include <fcntl.h>
2344d38a94Stedu #include <limits.h>
2444d38a94Stedu #include <sha2.h>
2544d38a94Stedu #include <stdio.h>
2644d38a94Stedu #include <stdlib.h>
2744d38a94Stedu #include <string.h>
2835d50e37Sderaadt #include <unistd.h>
2944d38a94Stedu
3044d38a94Stedu /* SHA256_DIGEST_STRING_LENGTH includes nul */
3144d38a94Stedu /* "/tmp/" + sha256 + ".shm" */
3244d38a94Stedu #define SHM_PATH_SIZE (5 + SHA256_DIGEST_STRING_LENGTH + 4)
3344d38a94Stedu
34dc519336Sguenther /* O_CLOEXEC and O_NOFOLLOW are extensions to POSIX */
35dc519336Sguenther #define OK_FLAGS (O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC | O_NOFOLLOW)
36dc519336Sguenther
3744d38a94Stedu static void
makeshmpath(const char * origpath,char * shmpath,size_t len)3844d38a94Stedu makeshmpath(const char *origpath, char *shmpath, size_t len)
3944d38a94Stedu {
4044d38a94Stedu char buf[SHA256_DIGEST_STRING_LENGTH];
4144d38a94Stedu
4244d38a94Stedu SHA256Data(origpath, strlen(origpath), buf);
4344d38a94Stedu snprintf(shmpath, len, "/tmp/%s.shm", buf);
4444d38a94Stedu }
4544d38a94Stedu
4644d38a94Stedu int
shm_open(const char * path,int flags,mode_t mode)4744d38a94Stedu shm_open(const char *path, int flags, mode_t mode)
4844d38a94Stedu {
4944d38a94Stedu char shmpath[SHM_PATH_SIZE];
5044d38a94Stedu struct stat sb;
5144d38a94Stedu int fd;
5244d38a94Stedu
53dc519336Sguenther if (((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
54dc519336Sguenther || (flags & ~(O_ACCMODE | OK_FLAGS))) {
5544d38a94Stedu errno = EINVAL;
5644d38a94Stedu return -1;
5744d38a94Stedu }
5844d38a94Stedu
5944d38a94Stedu flags |= O_CLOEXEC | O_NOFOLLOW;
6044d38a94Stedu mode = mode & 0600;
6144d38a94Stedu
6244d38a94Stedu makeshmpath(path, shmpath, sizeof(shmpath));
6344d38a94Stedu
64*81064d43Sguenther fd = HIDDEN(open)(shmpath, flags, mode);
6544d38a94Stedu if (fd == -1)
6644d38a94Stedu return -1;
6744d38a94Stedu if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
68*81064d43Sguenther HIDDEN(close)(fd);
69630d1d62Stedu errno = EINVAL;
7044d38a94Stedu return -1;
7144d38a94Stedu }
72a6da238dStedu if (sb.st_uid != geteuid()) {
73*81064d43Sguenther HIDDEN(close)(fd);
74630d1d62Stedu errno = EPERM;
7544d38a94Stedu return -1;
7644d38a94Stedu }
7744d38a94Stedu return fd;
7844d38a94Stedu }
79264376d6Sguenther DEF_WEAK(shm_open);
8044d38a94Stedu
8144d38a94Stedu int
shm_unlink(const char * path)8244d38a94Stedu shm_unlink(const char *path)
8344d38a94Stedu {
8444d38a94Stedu char shmpath[SHM_PATH_SIZE];
8544d38a94Stedu
8644d38a94Stedu makeshmpath(path, shmpath, sizeof(shmpath));
8744d38a94Stedu return unlink(shmpath);
8844d38a94Stedu }
8944d38a94Stedu
9044d38a94Stedu int
shm_mkstemp(char * template)9144d38a94Stedu shm_mkstemp(char *template)
9244d38a94Stedu {
9344d38a94Stedu size_t templatelen;
9444d38a94Stedu char *t;
9544d38a94Stedu int i, fd;
9644d38a94Stedu
9744d38a94Stedu templatelen = strlen(template);
9844d38a94Stedu t = malloc(templatelen + 1);
9944d38a94Stedu if (!t)
10044d38a94Stedu return -1;
10144d38a94Stedu t[templatelen] = '\0';
10244d38a94Stedu
10344d38a94Stedu fd = -1;
10444d38a94Stedu for (i = 0; i < INT_MAX; i++) {
10544d38a94Stedu memcpy(t, template, templatelen);
10644d38a94Stedu if (!_mktemp(t))
10744d38a94Stedu break;
10844d38a94Stedu fd = shm_open(t, O_RDWR | O_EXCL | O_CREAT, 0600);
10944d38a94Stedu if (fd != -1) {
11044d38a94Stedu memcpy(template, t, templatelen);
11144d38a94Stedu break;
11244d38a94Stedu }
11344d38a94Stedu }
11444d38a94Stedu
11544d38a94Stedu free(t);
11644d38a94Stedu return fd;
11744d38a94Stedu }
11844d38a94Stedu
119