GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/gen/shm_open.c Lines: 0 41 0.0 %
Date: 2017-11-13 Branches: 0 22 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: shm_open.c,v 1.9 2017/09/10 18:20:00 guenther 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
/* O_CLOEXEC and O_NOFOLLOW are extensions to POSIX */
35
#define OK_FLAGS	(O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC | O_NOFOLLOW)
36
37
static void
38
makeshmpath(const char *origpath, char *shmpath, size_t len)
39
{
40
	char buf[SHA256_DIGEST_STRING_LENGTH];
41
42
	SHA256Data(origpath, strlen(origpath), buf);
43
	snprintf(shmpath, len, "/tmp/%s.shm", buf);
44
}
45
46
int
47
shm_open(const char *path, int flags, mode_t mode)
48
{
49
	char shmpath[SHM_PATH_SIZE];
50
	struct stat sb;
51
	int fd;
52
53
	if (((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
54
	    || (flags & ~(O_ACCMODE | OK_FLAGS))) {
55
		errno = EINVAL;
56
		return -1;
57
	}
58
59
	flags |= O_CLOEXEC | O_NOFOLLOW;
60
	mode = mode & 0600;
61
62
	makeshmpath(path, shmpath, sizeof(shmpath));
63
64
	fd = HIDDEN(open)(shmpath, flags, mode);
65
	if (fd == -1)
66
		return -1;
67
	if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
68
		HIDDEN(close)(fd);
69
		errno = EINVAL;
70
		return -1;
71
	}
72
	if (sb.st_uid != geteuid()) {
73
		HIDDEN(close)(fd);
74
		errno = EPERM;
75
		return -1;
76
	}
77
	return fd;
78
}
79
DEF_WEAK(shm_open);
80
81
int
82
shm_unlink(const char *path)
83
{
84
	char shmpath[SHM_PATH_SIZE];
85
86
	makeshmpath(path, shmpath, sizeof(shmpath));
87
	return unlink(shmpath);
88
}
89
90
int
91
shm_mkstemp(char *template)
92
{
93
	size_t templatelen;
94
	char *t;
95
	int i, fd;
96
97
	templatelen = strlen(template);
98
	t = malloc(templatelen + 1);
99
	if (!t)
100
		return -1;
101
	t[templatelen] = '\0';
102
103
	fd = -1;
104
	for (i = 0; i < INT_MAX; i++) {
105
		memcpy(t, template, templatelen);
106
		if (!_mktemp(t))
107
			break;
108
		fd = shm_open(t, O_RDWR | O_EXCL | O_CREAT, 0600);
109
		if (fd != -1) {
110
			memcpy(template, t, templatelen);
111
			break;
112
		}
113
	}
114
115
	free(t);
116
	return fd;
117
}
118