xref: /openbsd-src/lib/libc/gen/shm_open.c (revision 81064d433281cbb881394cc726b6ecbb9268d4ee)
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